Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

keycloak server #11

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions Keycloak/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Keycloak Server Automation with Terraform

Terraform configurations for automating the deployment of a Keycloak server on AWS. The deployment script provisions an EC2 instance with Keycloak installed and configured, using specified AWS resources and settings.

## Prerequisites

Before you begin, ensure you have the following:

- **Terraform**: Make sure Terraform is installed on your local machine. You can download it from [Terraform's official website](https://www.terraform.io/downloads.html).


## Configuration

1. Clone the Repository

```
git clone <repository-url>
cd <repository-directory>
```

2. Update `terraform.tfvars`

Edit the terraform.tfvars file with your specific AWS and Keycloak configurations:

4. Initialize Terraform

Run the following command to initialize Terraform. This will download the necessary provider plugins:

```
terraform init
```
6. Plan the Deployment

Create an execution plan to review the resources that Terraform will create or modify:
```
terraform plan
```
7. Apply the Configuration

Apply the Terraform configuration to create the resources:
```
terraform apply
```
Confirm the action by typing `yes` when prompted.

## Keycloak Access
Once the deployment is complete, you can access your Keycloak server using the provided domain.
~~~
Admin URL: https://prefix-keycloak.test.rancher.space
Admin Username: admin
Admin Password: The password specified in `terraform.tfvars`.
~~~

Cleanup:

To remove the resources created by Terraform, run:
```
terraform destroy
```
Confirm the action by typing `yes` when prompted.

# Important Notice
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it's better to use the WARNING.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more of an Important Notice because it provides critical information about the intended use, lack of warranties, and the absence of official support. It doesn't explicitly warn of an immediate danger but clarifies important terms that users must be aware of before proceeding. so I believe, in its current form, "Important Notice" is the appropriate term....


This deployment is intended for internal use only and is not suitable for production environments or customer deployments. It is provided as-is, without any warranties or guarantees. There is no official support provided by SUSE for this deployment.

# Additional Information

Feel free to customize the content further based on your specific project details and preferences.
53 changes: 53 additions & 0 deletions Keycloak/cloud-init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash
apt update -y
apt install -y docker*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use an openSUSE Leap VM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the script is a sample for internal use, the choice between Ubuntu and openSUSE Leap may depend on what the individual is comfortable with.

Any more specific reasons why openSUSE Leap would be a better fit in this context or a dependency that Keycloak/rancher?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any more specific reasons why openSUSE Leap would be a better fit in this context or a dependency that Keycloak/rancher?

No specific reason at all other than the proverb eat your own dog food.

systemctl enable --now docker.service


# Generate certificates using Docker
docker run -v $PWD/certs:/certs \
-e CA_SUBJECT="My own root CA" \
-e CA_EXPIRE="1825" \
-e SSL_EXPIRE="365" \
-e SSL_SUBJECT="${keycloak_server_name}" \
-e SSL_DNS="${keycloak_server_name}" \
-e SILENT="true" \
superseb/omgwtfssl
Copy link

@dharmit dharmit Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

superseb/omgwtfssl was updated almost 6 years ago. Can we maybe create an image using it as base image and update it for CVEs and such?

EDIT: Just a simple apt/zypper/dnf update would suffice. However, if it's based on a container image that's no longer maintained, e.g. ubuntu 20.10, it might be better to find the Dockerfile and create our own image based on a openSUSE base, if possible, or simply use latest container of ubuntu/fedora whatever the original image is using.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the SSL creation process using Certbot.


# Combine certificate and CA into fullchain.pem
cat certs/cert.pem certs/ca.pem > certs/fullchain.pem


# Set up Keycloak certificates directory
mkdir -p /opt/keycloak/certs
cp certs/fullchain.pem /opt/keycloak/certs/
cp certs/key.pem /opt/keycloak/certs/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
mkdir -p /opt/keycloak/certs
cp certs/fullchain.pem /opt/keycloak/certs/
cp certs/key.pem /opt/keycloak/certs/
KEYCLOAK_CERTS=/opt/keycloak/certs
mkdir -p $KEYCLOAK_CERTS
cp certs/fullchain.pem $KEYCLOAK_CERTS
cp certs/key.pem $KEYCLOAK_CERTS



cat <<EOF > /opt/keycloak/keycloak.yml
version: '3'
services:
keycloak:
image: quay.io/keycloak/keycloak:latest
container_name: keycloak
restart: always
ports:
- 80:8080
- 443:8443
volumes:
- ./certs/fullchain.pem:/etc/x509/https/tls.crt
- ./certs/key.pem:/etc/x509/https/tls.key
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=${keycloak_password}
- KC_HOSTNAME=${keycloak_server_name}
- KC_HTTPS_CERTIFICATE_FILE=/etc/x509/https/tls.crt
- KC_HTTPS_CERTIFICATE_KEY_FILE=/etc/x509/https/tls.key
command:
- start-dev
EOF

# Start Keycloak with Docker Compose
curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-compose
chmod +x /usr/bin/docker-compose
docker-compose -f /opt/keycloak/keycloak.yml up
76 changes: 76 additions & 0 deletions Keycloak/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
provider "aws" {
region = var.region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
}

data "aws_route53_zone" "selected" {
name = var.aws_domain
private_zone = false
}

data "template_file" "keycloak" {
template = file("cloud-init.sh")
vars = {
keycloak_server_name = "${var.instance_suffix}-keycloak.${var.aws_domain}"
keycloak_password = var.keycloak_password
}
}

resource "aws_instance" "keycloak" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = var.subnet_id
vpc_security_group_ids = var.security_group_ids
key_name = var.key_name

associate_public_ip_address = true

user_data = data.template_file.keycloak.rendered

tags = {
Name = "${var.instance_suffix}-keycloak"
}
}

resource "aws_route53_record" "dns" {
zone_id = data.aws_route53_zone.selected.zone_id
name = "${var.instance_suffix}-keycloak"
type = "A"
ttl = 300
records = [aws_instance.keycloak.public_ip]
}

resource "null_resource" "keycloak_readiness_check" {
provisioner "local-exec" {
command = <<EOT
#!/bin/bash

timeout=300 # Maximum time to wait in seconds
interval=20 # Time to wait between checks in seconds
end_time=$(( $(date +%s) + timeout ))

while [ $(date +%s) -lt $end_time ]; do
if curl -k -s -o /dev/null -w "%%{http_code}" -L https://${data.template_file.keycloak.vars.keycloak_server_name} | grep -q '^200$'; then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A code comment explaining what this is doing would help everyone if something needs to be changed in future. Especially folks like me who aren't shell script experts.

echo "Keycloak is ready!"
exit 0
fi
echo "Keycloak not ready yet. Waiting $interval seconds..."
sleep $interval
done

echo "Timeout reached. Keycloak service is not ready."
exit 1
EOT
}

depends_on = [aws_route53_record.dns]
}

output "keycloak_server_ip" {
value = aws_instance.keycloak.public_ip
}

output "keycloak_server_name" {
value = "https://${data.template_file.keycloak.vars.keycloak_server_name}"
}
35 changes: 35 additions & 0 deletions Keycloak/terraform.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# terraform.tfvars

# AWS region to deploy the instance
region = "us-east-2"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since most of the team is based in India, could we use ap-south-1 for convenience?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve included instructions in the README.md that guide users to customize the terraform.tfvars file with their specific AWS configurations, including the region. Just edit the terraform.tfvars file with the preferred region and other relevant settings.


# AWS credentials
aws_access_key = "" # Replace with your AWS Access Key
aws_secret_key = "" # Replace with your AWS Secret Key

# EC2 instance type
instance_type = "t3.medium"

# Name of the SSH key pair to use for the EC2 instance
key_name = "" # Replace with your actual key pair name

# VPC ID where the EC2 instance will be deployed
vpc_id = "" # Replace with your actual VPC ID

# Subnet ID within the VPC where the EC2 instance will be deployed
subnet_id = "" # Replace with your actual Subnet ID

# Security Group IDs associated with the EC2 instance
security_group_ids = [""] # Replace with your actual Security Group IDs

# AMI ID for the EC2 instance
ami_id = ""

# AWS Route 53 domain name
aws_domain = ""

# Suffix to append to the instance name and DNS record
instance_suffix = "" # e.g., 'dev', 'prod', or any other environment identifier

# Keycloak admin password
keycloak_password = "" # Replace with a secure password
57 changes: 57 additions & 0 deletions Keycloak/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
variable "region" {
description = "AWS region"
type = string
default = "us-east-2"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same request about ap-south-1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed a default region... so you need to set it up from tf.vars

}

variable "aws_access_key" {
description = "AWS access key"
type = string
}

variable "aws_secret_key" {
description = "AWS secret key"
type = string
sensitive = true
}

variable "instance_type" {
description = "EC2 instance type"
default = "t3.medium"
}

variable "key_name" {
description = "The name of the key pair to use for the instance"
}

variable "vpc_id" {
description = "The VPC ID where the instance will be deployed"
}

variable "subnet_id" {
description = "The Subnet ID where the instance will be deployed"
}

variable "security_group_ids" {
description = "List of security group IDs to associate with the instance"
type = list(string)
}

variable "ami_id" {
description = "The AMI ID to use for the instance"
default = "ami-0862be96e41dcbf74"
}

variable "aws_domain" {
description = "The domain name for the AWS Route 53"
}

variable "instance_suffix" {
description = "Suffix to append to the instance name"
}

variable "keycloak_password" {
description = "Keycloak admin password"
type = string
default = "password"
}