SSL/TLS: Wildcard Certificate Generation 
Tested and working on 11/15/2023 !

# Create root CA
[acool@localhost tls]$openssl req --x509 --nodes --days 3650 --newkey rsa:2048 --keyout ENT-CA.key --out ENT-CA.crt

# Crate new key and signing request (Tip: remove --aes256 to remove passphrase requirement... I think)
Passphrase: mypassphrase
[acool@localhost tls]$openssl genrsa --out star-dev-localhost.key --aes256 2048
[acool@localhost tls]$openssl req --new --key star-dev-localhost.key --out star-dev-localhost.csr

# Sign request
[acool@localhost tls]$openssl x509 --req --in star-dev-localhost.csr --CA ENT-CA.crt --CAkey ENT-CA.key --CAcreateserial --days 3650 --sha256 --extfile star-dev-localhost.cnf --out star-dev-localhost.crt

# remove passphrase
[acool@localhost tls]$openssl rsa --in star-dev-localhost.key --out star-dev-localhost-nopassphrase.key

[acool@localhost tls]$ cat star-dev-localhost.cnf
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.dev.localhost
[acool@localhost tls]$
[acool@localhost tls]


# finally, import ENT-CA.crt certificate in Chrome
# chrome://settings/certificates


Configure Nginx:
...
listen 443 ssl;
ssl_certificate /etc/ssl/certs/star-dev-localhost.crt;
ssl_certificate_key /etc/ssl/certs/star-dev-localhost-nopassphrase.key;
...


[ view entry ] ( 243 views )   |  print article
C 101: Foreach loop macro 
[acool@localhost ~]$ 
[acool@localhost ~]$ date
Mon Apr 3 11:17:50 AM PDT 2023
[acool@localhost ~]$
[acool@localhost ~]$ cat c-foreach-macro.c
#include <stdio.h>

#define foreach(item, array) \
for(int keep = 1, \
count = 0,\
size = sizeof (array) / sizeof *(array); \
keep && count != size; \
keep = !keep, count++) \
for(item = (array) + count; keep; keep = !keep)

int main()
{
int mynumbers[] = {5,20,35,62,8,74,89};

char mygreeting[] = {"Hello world!"};

float myfloats[] = {1.6,6.9,5.8,43.5,1.1,0.9};

foreach(int *v, mynumbers) {
printf("value: %d\n", *v);
}

foreach(char *v, mygreeting) {
printf("value: %c\n", *v);
}

foreach(float *v, myfloats) {
printf("value: %.2f\n", *v);
}

return 0;
}
[acool@localhost ~]$
[acool@localhost ~]$ gcc c-foreach-macro.c -o c-foreach-macro
[acool@localhost ~]$
[acool@localhost ~]$ ./c-foreach-macro
value: 5
value: 20
value: 35
value: 62
value: 8
value: 74
value: 89
value: H
value: e
value: l
value: l
value: o
value:
value: w
value: o
value: r
value: l
value: d
value: !
value:
value: 1.60
value: 6.90
value: 5.80
value: 43.50
value: 1.10
value: 0.90
[acool@localhost ~]$


Bonus - dumping output from preprocessor.
[acool@localhost ~]$ 
[acool@localhost ~]$ gcc c-foreach-macro.c -E -o c-macro.preprocessed
[acool@localhost ~]$
[acool@localhost ~]$ cat c-macro.preprocessed
...
int main()
{
int mynumbers[] = {5,20,35,62,8,74,89};

char mygreeting[] = {"Hello world!"};

float myfloats[] = {1.6,6.9,5.8,43.5,1.1,0.9};

for(int keep = 1, count = 0, size = sizeof (mynumbers) / sizeof *(mynumbers); keep && count != size; keep = !keep, count++) for(int *v = (mynumbers) + count; keep; keep = !keep) {
printf("value: %d\n", *v);
}

for(int keep = 1, count = 0, size = sizeof (mygreeting) / sizeof *(mygreeting); keep && count != size; keep = !keep, count++) for(char *v = (mygreeting) + count; keep; keep = !keep) {
printf("value: %c\n", *v);
}

for(int keep = 1, count = 0, size = sizeof (myfloats) / sizeof *(myfloats); keep && count != size; keep = !keep, count++) for(float *v = (myfloats) + count; keep; keep = !keep) {
printf("value: %.2f\n", *v);
}

return 0;
}
[acool@localhost ~]$


[ view entry ] ( 272 views )   |  print article
C 101: Creating Child Processes With A Loop 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void child( int seconds );

int children = 15;

int main(void)
{
printf("Parent ID %d, Main ID %d \n", getppid(), getpid());

for(int i=0;i<children;i++)
{
if(fork()==0)
{
child(children-i); // pass seconds to sleep
}
else
{
wait(NULL);
}
}
}

void child(int seconds)
{
printf("Parent ID %d, Child ID %d, Sleeping %d seconds.\n", getppid(), getpid(), seconds);
sleep(seconds);
exit(0);
}

[acool@localhost C-Exercises]$ date
Sun Oct 23 04:14:24 PM PDT 2022
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ gcc parent_children.c
[acool@localhost C-Exercises]$ ./a.out
Parent ID 4298, Main ID 10357
Parent ID 10357, Child ID 10358, Sleeping 15 seconds.
Parent ID 10357, Child ID 10394, Sleeping 14 seconds.
Parent ID 10357, Child ID 10436, Sleeping 13 seconds.
Parent ID 10357, Child ID 10475, Sleeping 12 seconds.
Parent ID 10357, Child ID 10510, Sleeping 11 seconds.
Parent ID 10357, Child ID 10532, Sleeping 10 seconds.
Parent ID 10357, Child ID 10546, Sleeping 9 seconds.
Parent ID 10357, Child ID 10558, Sleeping 8 seconds.
Parent ID 10357, Child ID 10581, Sleeping 7 seconds.
Parent ID 10357, Child ID 10598, Sleeping 6 seconds.
Parent ID 10357, Child ID 10607, Sleeping 5 seconds.
Parent ID 10357, Child ID 10613, Sleeping 4 seconds.
Parent ID 10357, Child ID 10647, Sleeping 3 seconds.
Parent ID 10357, Child ID 10732, Sleeping 2 seconds.
Parent ID 10357, Child ID 10815, Sleeping 1 seconds.
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ ps -A |grep a.out
10357 pts/0 00:00:00 a.out
10394 pts/0 00:00:00 a.out
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ pstree -p 10357
a.out(10357)───a.out(10436)
[acool@localhost C-Exercises]$

Slightly different version, in this version we don't wait() for each child individually.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

void child( int seconds );

int children = 15;

int main(void)
{
printf("Parent ID %d, Main ID %d \n", getppid(), getpid());

for(int i=0;i<children;i++)
{
if(fork()==0)
{
child(children-i); // pass seconds to sleep
}
}

while (wait(NULL) > 0); // wait for all children to finish
}

void child(int seconds)
{
printf("Parent ID %d, Child ID %d, Sleeping %d seconds.\n", getppid(), getpid(), seconds);
sleep(seconds);
exit(0);
}

[acool@localhost C-Exercises]$ 
[acool@localhost C-Exercises]$ gcc parent_children.c
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ ./a.out
Parent ID 4298, Main ID 14322
Parent ID 14322, Child ID 14323, Sleeping 15 seconds.
Parent ID 14322, Child ID 14324, Sleeping 14 seconds.
Parent ID 14322, Child ID 14325, Sleeping 13 seconds.
Parent ID 14322, Child ID 14326, Sleeping 12 seconds.
Parent ID 14322, Child ID 14327, Sleeping 11 seconds.
Parent ID 14322, Child ID 14328, Sleeping 10 seconds.
Parent ID 14322, Child ID 14329, Sleeping 9 seconds.
Parent ID 14322, Child ID 14330, Sleeping 8 seconds.
Parent ID 14322, Child ID 14331, Sleeping 7 seconds.
Parent ID 14322, Child ID 14332, Sleeping 6 seconds.
Parent ID 14322, Child ID 14333, Sleeping 5 seconds.
Parent ID 14322, Child ID 14334, Sleeping 4 seconds.
Parent ID 14322, Child ID 14335, Sleeping 3 seconds.
Parent ID 14322, Child ID 14336, Sleeping 2 seconds.
Parent ID 14322, Child ID 14337, Sleeping 1 seconds.
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ pstree -p 14322
a.out(14322)─┬─a.out(14323)
├─a.out(14324)
├─a.out(14325)
├─a.out(14326)
├─a.out(14327)
├─a.out(14328)
├─a.out(14329)
├─a.out(14330)
├─a.out(14331)
├─a.out(14332)
├─a.out(14333)
├─a.out(14334)
└─a.out(14335)
[acool@localhost C-Exercises]$ ps -A |grep a.out
14322 pts/0 00:00:00 a.out
14323 pts/0 00:00:00 a.out
14324 pts/0 00:00:00 a.out
14325 pts/0 00:00:00 a.out
14326 pts/0 00:00:00 a.out
14327 pts/0 00:00:00 a.out
14328 pts/0 00:00:00 a.out
14329 pts/0 00:00:00 a.out
14330 pts/0 00:00:00 a.out
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$ pstree -p 14322
a.out(14322)─┬─a.out(14323)
├─a.out(14324)
├─a.out(14325)
├─a.out(14326)
├─a.out(14327)
└─a.out(14328)
[acool@localhost C-Exercises]$
[acool@localhost C-Exercises]$


[ view entry ] ( 302 views )   |  print article
C101: Printing Emojis 
#include <stdio.h>
#include <wchar.h>
#include <locale.h>

// multibyte array, each character is 4 bytes long
wchar_t mystring[] = L"Angel Cool á 🤪 😁 ა";

// [acool@localhost other]$ gcc -Wall -ggdb emoji-multibyte-array.c -o emoji-multibyte-array
int main()
{
setlocale(LC_ALL,"");

// print total number of characters in string
wprintf(L"wcslen of wchar_t mystring[]: %ld\n", wcslen(mystring));

// output string
wprintf(L"%ls\n",mystring);

// print one character
wprintf(L"Emoji : %lc\n", mystring[13]);

// print all
for (int j = 0; j < wcslen(mystring); ++j)
{
wprintf(L"%lc,", mystring[j]);
}

wprintf(L"\n");

// size in bytes of string, it also includes 4 bytes for the null (\0) characters at the end it seems
wprintf(L"Size in bytes of mystring[]: %d\n", sizeof(mystring));

// print size of wchar_t data type
wprintf(L"wchar_t is %d bytes long!\n", sizeof(wchar_t));

return 0;
}

[acool@localhost other]$ date
Sat Oct 22 12:05:24 PM PDT 2022
[acool@localhost other]$ gcc emoji-multibyte-array.c
[acool@localhost other]$ ./a.out
wcslen of wchar_t mystring[]: 18
Angel Cool á 🤪 😁 ა
Emoji : 🤪
A,n,g,e,l, ,C,o,o,l, ,á, ,🤪, ,😁, ,ა,
Size in bytes of mystring[]: 76
wchar_t is 4 bytes long!
[acool@localhost other]$


[ view entry ] ( 270 views )   |  print article
C 101: Preventing Zombie Processes  
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
pid_t pid;
int status;

pid = fork();

if(pid<0)
{
printf("Error: fork() returned %u.\n", pid);
return 1;
}

if(pid == 0)
{
printf("Child: PID is %u. Parent's PID is %u\n", getpid(), getppid());
sleep(10);
puts("Child: about to exit.\n");
return 33;
}
else
{
printf("Parent: PID is %u. Child's PID is %u\n", getpid(), pid);

while((pid=waitpid(-1,&status,WNOHANG)) == 0)
{
printf("Parent: No child has terminated.");
printf("Parent: Going to sleep for 1 second.\n");
sleep(1);
}
}

printf("Parent: child with PID %u ", pid);

if(WIFEXITED(status)!=0)
{
printf("exited with status %u\n",WIFEXITED(status));
}
else
{
printf("exited abnormally\n");
}

return 0;
}

Preventing Zombie Processes Using waitpid()
Listing 19.5 -Teach Yourself C For Linux Programming
[acool@localhost C-practice]$ gcc -Wall fork.c
[acool@localhost C-practice]$
[acool@localhost C-practice]$ ./a.out
Parent: PID is 57544. Child's PID is 57545
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Child: PID is 57545. Parent's PID is 57544
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Parent: No child has terminated.Parent: Going to sleep for 1 second.
Child: about to exit.

Parent: child with PID 57545 exited with status 1
[acool@localhost C-practice]$
[acool@localhost C-practice]$


[ view entry ] ( 302 views )   |  print article
C 101: Creating Structures 
Method 1:
// define it as a template
struct person {
char first_name[50];
char last_name[50];
};

// create two instances of person
struct person Person1, Person2;

// assign values to Person1
strcpy(Person1.first_name, "Angel");
strcpy(Person1.last_name, "Cool");

Method 2:
// define it and create two instances of it
struct car {
char make[50];
char color[50];
} Car1, Car2;

// assign values to Car1
strcpy(Car1.make, "Chevy");
strcpy(Car1.color, "red");

Method 3:
// use 'typedef' to create it
typedef struct {
char first_name[50];
char last_name[50];
} person;

// create two instances of person (no 'struct' keyword needed)
person Person1, Person2;

Method 1 example
[acool@localhost C-practice]$ 
[acool@localhost C-practice]$ cat method_1.c
#include <stdio.h>
#include <string.h>

void main(){
struct person {
char first_name[50];
char last_name[50];
};

// create two instances of person
struct person Person1, Person2;

// assign values to Person1
strcpy(Person1.first_name, "Angel");
strcpy(Person1.last_name, "Cool");

// print assigned values
printf("Hello %s %s!\n", Person1.first_name, Person1.last_name);
}
[acool@localhost C-practice]$ gcc method_1.c -o method_1
[acool@localhost C-practice]$ ./method_1
Hello Angel Cool!
[acool@localhost C-practice]$

Method 2 example
[acool@localhost C-practice]$ 
[acool@localhost C-practice]$ cat method_2.c
#include <stdio.h>
#include <string.h>

void main(){
// define it and create two instances of it
struct car {
char make[50];
char color[50];
} Car1, Car2;

// assign values to Car1
strcpy(Car1.make, "Chevy");
strcpy(Car1.color, "red");

// print assigned values
printf("My %s %s.\n",Car1.color, Car1.make);
}
[acool@localhost C-practice]$
[acool@localhost C-practice]$ gcc method_2.c -o method_2
[acool@localhost C-practice]$ ./method_2
My red Chevy.
[acool@localhost C-practice]$

Method 3 example
[acool@localhost C-practice]$ 
[acool@localhost C-practice]$ cat method_3.c
#include <stdio.h>
#include <string.h>

void main(){
// use 'typedef' to create it
typedef struct {
char first_name[50];
char last_name[50];
} person;

// create two instances of person (no 'struct' keyword needed)
person Person1, Person2;

// assign values to Person1
strcpy(Person1.first_name, "Andres Manuel");
strcpy(Person1.last_name, "Lopez-Obrador");

printf("Viva la 4T! Viva %s %s!\n", Person1.first_name, Person1.last_name);
}
[acool@localhost C-practice]$
[acool@localhost C-practice]$ gcc method_3.c -o method_3
[acool@localhost C-practice]$ ./method_3
Viva la 4T! Viva Andres Manuel Lopez-Obrador!
[acool@localhost C-practice]$
[acool@localhost C-practice]$


Another example:
[acool@localhost ~]$ 
[acool@localhost ~]$
[acool@localhost ~]$ date
Wed Apr 5 02:18:30 PM PDT 2023
[acool@localhost ~]$
[acool@localhost ~]$ cat books.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Books {
char title[50];
char author[50];
char subject[100];
int id;
};

typedef struct {
char title[50];
char author[50];
char subject[100];
int id;
} eBooks;

void printdetails(eBooks *myEbook, struct Books *myBook)
{
printf( "myBook id : %d\n", myBook->id);
printf( "myBook title : %s\n", myBook->title);
printf( "myBook author : %s\n", myBook->author);
printf( "myBook subject : %s\n", myBook->subject);

printf("====================================\n");

printf( "myEbook id : %d\n", myEbook->id);
printf( "myEbook title : %s\n", myEbook->title);
printf( "myEbook author : %s\n", myEbook->author);
printf( "myEbook subject : %s\n", myEbook->subject);
}

int main()
{
// Pay attention to this! ...two different ways to declare it.
struct Books *myBook = (struct Books *) malloc(sizeof(struct Books));
eBooks *myEbook = (eBooks *) malloc(sizeof(eBooks));

strcpy( myBook->title, "C Programming");
strcpy( myBook->author, "Angel Cool");
strcpy( myBook->subject, "Programming C Structs Examples");
myBook->id = 1;

strcpy( myEbook->title, "C Programming (eBook)");
strcpy( myEbook->author, "Angel Cool (eBook)");
strcpy( myEbook->subject, "Programming C Structs Examples (eBook)");
myEbook->id = 2;

printdetails(myEbook,myBook);

return 0;
}
[acool@localhost ~]$
[acool@localhost ~]$
[acool@localhost ~]$ gcc books.c -o books
[acool@localhost ~]$
[acool@localhost ~]$ ./books
myBook id : 1
myBook title : C Programming
myBook author : Angel Cool
myBook subject : Programming C Structs Examples
====================================
myEbook id : 2
myEbook title : C Programming (eBook)
myEbook author : Angel Cool (eBook)
myEbook subject : Programming C Structs Examples (eBook)
[acool@localhost ~]$
[acool@localhost ~]$ file books
books: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=ea1090588d4c761da3060066a7d7a67b7db9caa6, for GNU/Linux 3.2.0, not stripped
[acool@localhost ~]$
[acool@localhost ~]$


[ view entry ] ( 321 views )   |  print article
Terraform: AWS VPC with IPV6 support 
[acool@localhost EC2-VPC]$ 
[acool@localhost EC2-VPC]$ date
Sun Jul 4 06:19:34 PM PDT 2021
[acool@localhost EC2-VPC]$ cat /etc/redhat-release
Fedora release 33 (Thirty Three)
[acool@localhost EC2-VPC]$ aws --version
aws-cli/1.18.223 Python/3.9.5 Linux/5.12.13-200.fc33.x86_64 botocore/1.19.63
[acool@localhost EC2-VPC]$ terraform -v
Terraform v1.0.1
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v3.48.0
[acool@localhost EC2-VPC]$

The gist of this post:
 
[acool@localhost EC2-VPC]$
[acool@localhost EC2-VPC]$ cat main.tf
# extract public ssh key from private ssh key
# [acool@localhost EC2-VPC]$ ssh-keygen -y -f ./COOL_SSH_PRIVATEKEY.pem > COOL_SSH_PUBLICKEY.pub

// a.- set region to use
provider "aws" {
region = "us-east-2"
}

// b.- create ssh key pair
resource "aws_key_pair" "COOL_KEY_PAIR" {
key_name = "COOL_SSH_KEYPAIR"
public_key = "${file("./COOL_SSH_PUBLICKEY.pub")}"
}

// c.- create vpc resource
resource "aws_vpc" "COOL_VPC" {
enable_dns_support = true
enable_dns_hostnames = true
assign_generated_ipv6_cidr_block = true
cidr_block = "10.0.0.0/16"
}

// d.- create subnet
resource "aws_subnet" "COOL_VPC_SUBNET" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.cidr_block, 4, 1)}"
map_public_ip_on_launch = true

ipv6_cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.ipv6_cidr_block, 8, 1)}"
assign_ipv6_address_on_creation = true
}

// e.- create internet gateway
resource "aws_internet_gateway" "COOL_GATEWAY" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
}

// f.- create routing table
resource "aws_default_route_table" "COOL_VPC_ROUTING_TABLE" {
default_route_table_id = "${aws_vpc.COOL_VPC.default_route_table_id}"

route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}

route {
ipv6_cidr_block = "::/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}
}

// g.- create some sort of association needed
resource "aws_route_table_association" "COOL_SUBNET_ROUTE_TABLE_ASSOCIATION" {
subnet_id = "${aws_subnet.COOL_VPC_SUBNET.id}"
route_table_id = "${aws_default_route_table.COOL_VPC_ROUTING_TABLE.id}"
}

// h.- create security group
resource "aws_security_group" "COOL_SECURITY_GROUP" {
name = "COOL_SECURITY_GROUP"
vpc_id = "${aws_vpc.COOL_VPC.id}"

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
ipv6_cidr_blocks = ["::/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmpv6"
ipv6_cidr_blocks = ["::/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
ipv6_cidr_blocks = ["::/0"]
}
}

// i.- create EC2 instance
resource "aws_instance" "COOL_INSTANCE_APP01" {
ami = "ami-01d5ac8f5f8804300"
key_name = "COOL_SSH_KEYPAIR"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.COOL_VPC_SUBNET.id}"
ipv6_address_count = 1
vpc_security_group_ids = ["${aws_security_group.COOL_SECURITY_GROUP.id}"]

tags = {
Name = "COOL_INSTANCE_APP01"
}

depends_on = [aws_internet_gateway.COOL_GATEWAY]
}

//j.- print instance IPs
output "COOL_INSTANCE_APP01_IPv4" {
value = "${aws_instance.COOL_INSTANCE_APP01.public_ip}"
}

output "COOL_INSTANCE_APP01_IPv6" {
value = ["${aws_instance.COOL_INSTANCE_APP01.ipv6_addresses}"]
}
[acool@localhost EC2-VPC]$
[acool@localhost EC2-VPC]$ terraform init
...
[acool@localhost EC2-VPC]$
[acool@localhost EC2-VPC]$ terraform apply
...
[acool@localhost EC2-VPC]$


Happy 4th of July, 2021! and cheers!


UPDATE - November 9, 2021
Added 'app_servers' variable to create multiple aws_instances.
Commit message: 'Added EIP and specified private ip addresses.'

main.tf :

# extract public ssh key from private ssh key
# [acool@localhost EC2-VPC]$ ssh-keygen -y -f ./COOL_SSH_PRIVATEKEY.pem > COOL_SSH_PUBLICKEY.pub

// set region to use
provider "aws" {
region = "us-east-2"
}

// create ssh key pair
resource "aws_key_pair" "COOL_KEY_PAIR" {
key_name = "COOL_SSH_KEYPAIR"
public_key = "${file("./COOL_SSH_PUBLICKEY.pub")}"
}

// create vpc resource
resource "aws_vpc" "COOL_VPC" {
enable_dns_support = true
enable_dns_hostnames = true
assign_generated_ipv6_cidr_block = true
cidr_block = "10.0.0.0/16"
}

// create subnet
resource "aws_subnet" "COOL_PVC_SUBNET" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.cidr_block, 4, 1)}"
map_public_ip_on_launch = true

ipv6_cidr_block = "${cidrsubnet(aws_vpc.COOL_VPC.ipv6_cidr_block, 8, 1)}"
assign_ipv6_address_on_creation = true
}

// create internet gateway
resource "aws_internet_gateway" "COOL_GATEWAY" {
vpc_id = "${aws_vpc.COOL_VPC.id}"
}

// create routing table
resource "aws_default_route_table" "COOL_VPC_ROUTING_TABLE" {
default_route_table_id = "${aws_vpc.COOL_VPC.default_route_table_id}"

route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}

route {
ipv6_cidr_block = "::/0"
gateway_id = "${aws_internet_gateway.COOL_GATEWAY.id}"
}
}

// create some sort of association needed
resource "aws_route_table_association" "COOL_SUBNET_ROUTE_TABLE_ASSOCIATION" {
subnet_id = "${aws_subnet.COOL_PVC_SUBNET.id}"
route_table_id = "${aws_default_route_table.COOL_VPC_ROUTING_TABLE.id}"
}

// create security group
resource "aws_security_group" "COOL_SECURITY_GROUP" {
name = "COOL_SECURITY_GROUP"
vpc_id = "${aws_vpc.COOL_VPC.id}"

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

ingress {
from_port = 22
to_port = 22
protocol = "tcp"
ipv6_cidr_blocks = ["::/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmpv6"
ipv6_cidr_blocks = ["::/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
ipv6_cidr_blocks = ["::/0"]
}
}

// server names
variable app_servers {
description = "name of app servers"
type = list(map(any))
default = [
{name:"COOL_LB01", ip:"10.0.16.4"},
{name:"COOL_LB02", ip:"10.0.16.5"},
{name:"COOL_APP01", ip:"10.0.16.6"},
{name:"COOL_APP02", ip:"10.0.16.7"},
]
}

// create EC2 instance
resource "aws_instance" "COOL_SERVERS" {
ami = "ami-01d5ac8f5f8804300"
key_name = "COOL_SSH_KEYPAIR"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.COOL_PVC_SUBNET.id}"
ipv6_address_count = 1
vpc_security_group_ids = ["${aws_security_group.COOL_SECURITY_GROUP.id}"]
for_each = {for server in var.app_servers: server.name => server}
private_ip = each.value["ip"]

tags = {
Name = each.value["name"]
}

depends_on = [aws_internet_gateway.COOL_GATEWAY]
}

// elastic IP
resource "aws_eip" "COOL_EIP" {
instance = aws_instance.COOL_SERVERS["COOL_LB01"].id
vpc = true
}

// print instance IPs
output "COOL_INSTANCE_APP01_IPv4" {
value = {for k, v in aws_instance.COOL_SERVERS: k => v.public_ip}
}

output "COOL_INSTANCE_APP01_IPv6" {
value = {for k, v in aws_instance.COOL_SERVERS: k => v.ipv6_addresses}
}

output "COOL_VPC_IPV6_BLOCK" {
value = aws_subnet.COOL_PVC_SUBNET.ipv6_cidr_block
}

// SSH to instance:
// [acool@localhost EC2-VPC]$ ssh -i ./COOL_SSH_PRIVATEKEY.pem centos@ip_address

// remove eip from COOL_LB01
// [acool@localhost EC2-VPC]$ aws ec2 disassociate-address --region us-east-2 --public-ip 3.131.249.150

// assign eip to COOL_LB02, adjust instance id to match LB02. The same commands work to return eip to LB01
// [acool@localhost EC2-VPC]$ aws ec2 associate-address --region us-east-2 --public-ip 3.131.249.150 --instance-id i-05a634252654b7b34



[ view entry ] ( 552 views )   |  print article
Terraform: AWS EC2 single instance example. 
[acool@localhost terraform-tests]$ terraform --version
Terraform v1.0.1
...
[acool@localhost terraform-tests]$ aws --version
aws-cli/1.18.223 Python/3.9.5 Linux/5.12.12-200.fc33.x86_64 botocore/1.19.63
...

The gist of this post:
[acool@localhost EC2-SINGLE-INSTANCE]$ cat main.tf 
provider "aws" {
region = "us-east-2"
}

// create ssh key
resource "tls_private_key" "COOL_SSH_PK" {
algorithm = "RSA"
rsa_bits = 4096
}

// create ssh key pair
resource "aws_key_pair" "COOL_KEY_PAIR" {
key_name = "COOL_SSH_KEYNAME"
public_key = tls_private_key.COOL_SSH_PK.public_key_openssh

provisioner "local-exec" { # Create "myKey.pem" to your computer!!
command = "echo '${tls_private_key.COOL_SSH_PK.private_key_pem}' > ./COOL_SSH_PK.pem"
}
}

// create aws ec2 instance
resource "aws_instance" "COOLAPP01" {
ami = "ami-01d5ac8f5f8804300"
instance_type = "t2.micro"
key_name = aws_key_pair.COOL_KEY_PAIR.key_name
vpc_security_group_ids = [aws_security_group.COOLAPP01_security_group.id]

tags = {
Name = "COOLAPP01_tag_name"
}
}

// create security group
resource "aws_security_group" "COOLAPP01_security_group" {

name="terraform_COOLAPP01_security_group"

// allow port 80 tcp
ingress{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow port 22 tcp
ingress{
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow ping
ingress{
from_port = -1
to_port = -1
protocol = "icmp"
cidr_blocks = ["0.0.0.0/0"]
}

// allow all outbound traffic
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

// TODO: enable IPV6

output "public_ip" {
value = aws_instance.COOLAPP01.public_ip
description = "public ip for COOLAPP01"
}
[acool@localhost EC2-SINGLE-INSTANCE]$
[acool@localhost EC2-SINGLE-INSTANCE]$terraform apply
...


Happy 4th of July, 2021 ya'll!!

[ view entry ] ( 442 views )   |  print article
Highly Available HAproxy Balancer with Keepalived 
We're gonna use Keepalived's VRRP feature.

Floating ip address will be 192.168.121.179

Vagrantfile needed parameters:

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.180"
config.vm.hostname = "lb01.localhost"

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.181"
config.vm.hostname = "lb02.localhost"

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.191"
config.vm.hostname = "app01.localhost"

config.vm.box = "centos/8"
config.vm.network "private_network", ip: "192.168.121.192"
config.vm.hostname = "app02.localhost"

------------------------------------------------------------------------
app01 and app02 will have nginx installed running its default welcome page.

angel@acool:~/Documents/haproxy-cluster$ date
Fri 21 May 2021 07:11:52 PM PDT
angel@acool:~/Documents/haproxy-cluster$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.2 LTS"
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$ tree
.
├── app01
│   └── Vagrantfile
├── app02
│   └── Vagrantfile
├── lb01
│   └── Vagrantfile
├── lb02
│   └── Vagrantfile
└── NOTES.txt

4 directories, 5 files
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$ sudo vagrant global-status
id name provider state directory
------------------------------------------------------------------------------
1553a24 default libvirt shutoff /home/angel/Documents/haproxy-cluster/lb01
3c33424 default libvirt shutoff /home/angel/Documents/haproxy-cluster/lb02
1d9af06 default libvirt shutoff /home/angel/Documents/haproxy-cluster/app01
5bc8220 default libvirt shutoff /home/angel/Documents/haproxy-cluster/app02
...
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster/lb01$ vagrant --version
Vagrant 2.2.6
angel@acool:~/Documents/haproxy-cluster$
angel@acool:~/Documents/haproxy-cluster$ cd lb01/
angel@acool:~/Documents/haproxy-cluster/lb01$ sudo vagrant up
...
angel@acool:~/Documents/haproxy-cluster/lb01$ sudo vagrant ssh
Last login: Sat May 22 02:08:45 2021 from 192.168.121.1
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/redhat-release
CentOS Linux release 8.3.2011
[vagrant@lb01 ~]$ sudo dnf install haproxy keepalived

[vagrant@lb01 ~]$ haproxy -v
HA-Proxy version 1.8.23 2019/11/25
Copyright 2000-2019 Willy Tarreau <willy@haproxy.org>

[vagrant@lb01 ~]$ keepalived --version
Keepalived v2.0.10 (11/12,2018)
...
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ # HAProxy need this to bind to floating ip when ip is missing locally
[vagrant@lb01 ~]$ cat /etc/sysctl.conf
...
net.ipv4.ip_nonlocal_bind=1
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ sudo sysctl -p
net.ipv4.ip_nonlocal_bind = 1
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/haproxy/haproxy.cfg
...
## enable stats
listen stats
bind :9000
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST

## enable www frontend, bind floating ip address
frontend www
bind 192.168.121.179:80
mode http
default_backend www_servers

## enable www backend
backend www_servers
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server app01 192.168.121.191:80 check
server app02 192.168.121.192:80 check

[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ cat /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
#script "killall -0 haproxy" # cheaper than pidof
script "pidof haproxy" # this one worked better for me.
interval 2 # check every 2 seconds
weight 2 # add 2 points of priority if OK
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 101 # 101 on lb01, 100 on lb02
virtual_ipaddress {
192.168.121.179
}
track_script {
chk_haproxy
}
}
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ # this should be the end result, the floating ip should be listed.
[vagrant@lb01 ~]$ ip a |grep 179
inet 192.168.121.179/32 scope global eth0
[vagrant@lb01 ~]$
[vagrant@lb01 ~]$ # if you stop haproxy (or shutdown lb01), lb02 should take over the floating ip!
[vagrant@lb01 ~]$ # when haproxy is back, lb01 will reclaim the floating ip, the end result is
[vagrant@lb01 ~]$ # the floating ip will be available even if lb01 goes down.


Cheers!

UPDATE: November 11, 2021 - Adding lb02 details in order to remove ambiguities when I see this post in the future.

[vagrant@lb02 ~]$ cat /etc/sysctl.conf
...
net.ipv4.ip_nonlocal_bind=1
[vagrant@lb02 ~]$


[vagrant@lb02 ~]$
[vagrant@lb02 ~]$
[vagrant@lb02 ~]$ cat /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
#script "killall -0 haproxy" # cheaper than pidof
script "pidof haproxy"
interval 2 # check every 2 seconds
weight 2 # add 2 points of priority if OK
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 100 # 101 on primary, 100 on secondary
virtual_ipaddress {
192.168.121.179
}
track_script {
chk_haproxy
}
}

[vagrant@lb02 ~]$


[vagrant@lb02 ~]$
[vagrant@lb02 ~]$
[vagrant@lb02 ~]$ cat /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# https://www.haproxy.org/download/1.8/doc/configuration.txt
#
#---------------------------------------------------------------------

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2

chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon

# turn on stats unix socket
stats socket /var/lib/haproxy/stats

# utilize system-wide crypto-policies
ssl-default-bind-ciphers PROFILE=SYSTEM
ssl-default-server-ciphers PROFILE=SYSTEM

#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000

# ME: enable stats
listen stats
bind :9000
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST

# ME:
frontend www
bind 192.168.121.179:80
mode http
default_backend www_servers

# ME:
backend www_servers
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
option httpchk HEAD / HTTP/1.1\r\nHost:localhost
server app01 192.168.121.191:80 check
server app02 192.168.121.192:80 check

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind *:5000
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js

use_backend static if url_static
default_backend app

#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
balance roundrobin
server static 127.0.0.1:4331 check

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
server app3 127.0.0.1:5003 check
server app4 127.0.0.1:5004 check
[vagrant@lb02 ~]$
[vagrant@lb02 ~]$





[ view entry ] ( 528 views )   |  print article
Docker: reference information for SWARMS, NODES, SERVICES, STACKS and NETWORKS 
[vagrant@box1 ~]$ date
Fri Dec 11 18:34:51 UTC 2020
[vagrant@box1 ~]$
[vagrant@box1 ~]$ docker --version
Docker version 20.10.0, build 7287ab3
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$ ########## Docker SWARM info ##########
[vagrant@box1 ~]$ docker swarm

Usage: docker swarm COMMAND

Manage Swarm

Commands:
ca Display and rotate the root CA
init Initialize a swarm
join Join a swarm as a node and/or manager
join-token Manage join tokens
leave Leave the swarm
unlock Unlock swarm
unlock-key Manage the unlock key
update Update the swarm

Run 'docker swarm COMMAND --help' for more information on a command.
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$ ########## Docker NODE info ##########
[vagrant@box1 ~]$ docker node

Usage: docker node COMMAND

Manage Swarm nodes

Commands:
demote Demote one or more nodes from manager in the swarm
inspect Display detailed information on one or more nodes
ls List nodes in the swarm
promote Promote one or more nodes to manager in the swarm
ps List tasks running on one or more nodes, defaults to current node
rm Remove one or more nodes from the swarm
update Update a node

Run 'docker node COMMAND --help' for more information on a command.
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$ ########## Docker SERVICE info ##########
[vagrant@box1 ~]$ docker service

Usage: docker service COMMAND

Manage services

Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services
update Update a service

Run 'docker service COMMAND --help' for more information on a command.
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$ ########## Docker STACK info ##########
[vagrant@box1 ~]$ docker stack

Usage: docker stack [OPTIONS] COMMAND

Manage Docker stacks

Options:
--orchestrator string Orchestrator to use (swarm|kubernetes|all)

Commands:
deploy Deploy a new stack or update an existing stack
ls List stacks
ps List the tasks in the stack
rm Remove one or more stacks
services List the services in the stack

Run 'docker stack COMMAND --help' for more information on a command.
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$ ########## Docker NETWORK info ##########
vagrant@box1 ~]$ docker network

Usage: docker network COMMAND

Manage networks

Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$ ########## All the crap available under Docker binary ##########
[vagrant@box1 ~]$
[vagrant@box1 ~]$ docker

Usage: docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
--config string Location of client config files (default "/home/vagrant/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker
context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket(s) to connect to
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/home/vagrant/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/home/vagrant/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/home/vagrant/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit

Management Commands:
app* Docker App (Docker Inc., v0.9.1-beta3)
builder Manage builds
buildx* Build with BuildKit (Docker Inc., v0.4.2-docker)
config Manage Docker configs
container Manage containers
context Manage contexts
image Manage images
manifest Manage Docker image manifests and manifest lists
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes

Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.
To get more help with docker, check out guides at https://docs.docker.com/go/guides/
[vagrant@box1 ~]$
[vagrant@box1 ~]$
[vagrant@box1 ~]$


[ view entry ] ( 548 views )   |  print article

<Back | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Next> Last>>


2024 By Angel Cool