Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions bin/packer.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ def contains(x, ys):

images = response['Images']
#images = [i for i in images if contains(i['Name'], ('hvm-ssd', '14.04', 'server'))]
images = [i for i in images if contains(i['Name'], ('hvm-ssd', '20.04', 'server'))]
images = [i for i in images if not contains(i['Name'], ('ubuntu-eks'))]
images = [i for i in images if not contains(i['Name'], ('ubuntu-pro-server'))]
images = [i for i in images if contains(i['Name'], ['hvm-ssd', '22.04', 'server'])]
images = [i for i in images if not contains(i['Name'], ['ubuntu-eks'])]
images = [i for i in images if not contains(i['Name'], ['ubuntu-pro-server'])]
images.sort(key=lambda x: x["CreationDate"], reverse=True)

if len(images) == 0:
Expand Down
4 changes: 2 additions & 2 deletions cloud_formation/configs/activities.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def create_config(bosslet_config, lookup=True):
const.INGEST_LAMBDA,
handler="index.handler",
timeout=60 * 5,
runtime='python3.7',
runtime='python3.11',
memory=3008)

config.add_lambda_permission("IngestLambdaExecute", Ref("IngestLambda"))
Expand Down Expand Up @@ -189,7 +189,7 @@ def create_config(bosslet_config, lookup=True):
lambda_role,
const.DOWNSAMPLE_DLQ_LAMBDA,
handler='index.handler',
runtime='python3.7',
runtime='python3.11',
timeout=10)

config.add_lambda_permission('DownsampleDLQLambdaExecute',
Expand Down
14 changes: 13 additions & 1 deletion cloud_formation/configs/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@
from lib import utils
from lib import constants as const


import json
import uuid
from urllib.request import Request, urlopen
from urllib.parse import urlencode
from urllib.error import HTTPError
from pprint import pprint

def create_config(bosslet_config, db_config={}):
names = bosslet_config.names
Expand Down Expand Up @@ -226,6 +228,7 @@ def create_config(bosslet_config, db_config={}):
db_config.get("user"),
db_config.get("password"),
internal_subnets,
rds_engine_version=bosslet_config.RDS_ENGINE_VERSION,
type_ = const.RDS_TYPE,
security_groups=[sgs[names.internal.sg]])

Expand Down Expand Up @@ -312,7 +315,8 @@ def create(bosslet_config):
raise

# Outside the try/except so it can be run again if there is an error
post_init(bosslet_config)
# post_init(bosslet_config)


def post_init(bosslet_config):
call = bosslet_config.call
Expand All @@ -330,17 +334,25 @@ def post_init(bosslet_config):
bossadmin = vault.read("secret/auth/realm")
auth_uri = vault.read("secret/endpoint/auth")['url']

# TODO Remove this debug statement
print(f"debug: {creds}\n{bossadmin}\n{auth_uri}")

# Verify Keycloak is accessible
print("Checking for Keycloak availability")
call.check_keycloak(const.TIMEOUT_KEYCLOAK)
print("Finished checking Keycloak availability")
pprint(names.auth)
pprint(names.auth.dns)

# Add the API servers to the list of OIDC valid redirects
with call.tunnel(names.auth.dns, 8080) as auth_port:
print("Update KeyCloak Client Info")
auth_url = "http://localhost:{}".format(auth_port)
with KeyCloakClient(auth_url, **creds) as kc:
# DP TODO: make add_redirect_uri able to work multiple times without issue
print("debug: about to add redirect URI")
kc.add_redirect_uri("BOSS","endpoint", uri + "/*")
print("debug: finished adding redirect URI")

# Get the boss admin's bearer token
headers = {
Expand Down
2 changes: 1 addition & 1 deletion cloud_formation/configs/cloudwatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def create_config(bosslet_config):
security_groups=[internal_sg],
subnets=lambda_subnets,
handler='index.lambda_handler',
runtime='python3.7',
runtime='python3.11',
file=const.VAULT_LAMBDA)

# Lambda input data
Expand Down
24 changes: 15 additions & 9 deletions cloud_formation/configs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ def create_config(bosslet_config):
aws.role_arn_lookup(session, 'DeleteENI'),
const.DELETE_ENI_LAMBDA,
handler="index.handler",
timeout=180, # 3 minutes, so that there is enough time to wait for the ENI detach to complete
runtime='python3.7') # If the lambda times out CF will retry a couple of times
timeout=180, # 3 minutes, so that there is enough time to wait for the ENI detach to complete
runtime='python3.11') # If the lambda times out CF will retry a couple of times

user_data = const.BASTION_USER_DATA.format(bosslet_config.NETWORK)
config.add_ec2_instance("Bastion",
Expand Down Expand Up @@ -202,6 +202,7 @@ def create_config(bosslet_config):
"keycloak",
"keycloak",
internal_subnets,
bosslet_config.RDS_ENGINE_VERSION,
type_=const.RDS_AUTH_TYPE,
security_groups=[Ref("InternalSecurityGroup")])

Expand All @@ -212,7 +213,7 @@ def create_config(bosslet_config):
const.DNS_LAMBDA,
handler="index.handler",
timeout=10,
runtime='python3.7',
runtime='python3.11',
depends_on="DNSZone")

config.add_lambda_permission("DNSLambdaExecute", Ref("DNSLambda"))
Expand Down Expand Up @@ -305,7 +306,9 @@ def create(bosslet_config):
vpc_id = aws.vpc_id_lookup(session, domain)
aws.rt_name_default(session, vpc_id, "default." + domain)

post_init(bosslet_config)
# TODO Sandy, put this back after debugging
# post_init(bosslet_config)


def post_init(bosslet_config):

Expand Down Expand Up @@ -334,11 +337,11 @@ def post_init(bosslet_config):
except Exception as ex:
raise BossManageError("Problem initializing Vault: {}".format(str(ex)))

#Check and see if these secrets already exist before we overwrite them with new ones.
# Check and see if these secrets already exist before we overwrite them with new ones.
# Write data into Vault
auth_data = vault.read(const.VAULT_AUTH)
if not auth_data or 'password' not in auth_data:
print("Writing {}".format(const.VAULT_AUTH))
print("Writing {} to vault".format(const.VAULT_AUTH))
vault.write(const.VAULT_AUTH, password = password, username = username, client_id = "admin-cli")
else:
password = auth_data['password']
Expand All @@ -356,7 +359,7 @@ def post_init(bosslet_config):

realm_data = vault.read(const.VAULT_REALM)
if not realm_data or 'password' not in realm_data:
print("Writing {}".format(const.VAULT_REALM))
print("Writing {} to vault".format(const.VAULT_REALM))
vault.write(const.VAULT_REALM, username = realm_username, password = realm_password, client_id = "endpoint")
else:
realm_password = realm_data['password']
Expand Down Expand Up @@ -386,14 +389,16 @@ def post_init(bosslet_config):
## Also need to guard the writes to vault with the admin password
#######

# Sandy TODO: Uncomment this after test on 1/14/2025
with call.ssh(names.auth.dns) as ssh:
print("Creating initial Keycloak admin user")
# This fails if the user already exists, but execution will continue.
ssh("/srv/keycloak/bin/add-user-keycloak.sh -r master -u {} -p {}".format(username, password))
time.sleep(10)
time.sleep(5)

print("Calling Keycloak jboss to reload Keycloak")
ssh("/srv/keycloak/bin/jboss-cli.sh --connect reload")
time.sleep(3)
time.sleep(20)

print("Waiting for Keycloak to restart")
call.check_keycloak(const.TIMEOUT_KEYCLOAK)
Expand Down Expand Up @@ -421,6 +426,7 @@ def post_init(bosslet_config):
except Exception as ex:
print('Failed to upload Boss.realm config. Does it already exist? Error message: {}'.format(ex))


def update(bosslet_config):
# Checks to make sure they update can happen and the user wants to wait the required time
if not bosslet_config.AUTH_RDS:
Expand Down
2 changes: 1 addition & 1 deletion cloud_formation/lambda/cache_throttle/lambda.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: cache_throttle
runtime: python3.7
runtime: python3.11
python_packages:
- requirements.txt
2 changes: 1 addition & 1 deletion cloud_formation/lambda/multi_lambda/lambda.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: multilambda
runtime: python3.7
runtime: python3.11
include:
# DP NOTE: The spdb, bossutils (boss-tools), and heaviside repositories
# are copied into repos/ where pip can install them from
Expand Down
15 changes: 13 additions & 2 deletions docs/InstallGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ from the root directory of the cloned boss-manage.git repository.*

### Workstation
You will need a machine installed with the following software packages:
* Python 3.8 or later
* Python 3.11
- The Boss Manage software can be run within `venv`, `virtualenv`, or `virtualenvwrapper`
- pip may need to be manually installed for Python 3.11
- $ pip install --upgrade setuptools
- $ python3 -m ensurepip --upgrade
- $ python3 -m pip install --user virtualenv virtualenvwrapper
- # if already present
- $ pip install --upgrade virtualenv virtualenvwrapper
- # you may need to run
- $ virtualenv --upgrade-embed-wheels
-
-
* Packer 1.8.x ([download](https://www.packer.io/)) (add it to your path or in the `boss-manage.git/bin/` directory)
* Docker Desktop ([download](https://docs.docker.com/desktop/release-notes/))
- Contact your department software representative to get a license
Expand Down Expand Up @@ -54,6 +64,7 @@ To install the Python packages needed for boss-manage to work, run

```shell
pip install -r requirements.txt
pip install -r heaviside-requirements.txt
```

## Setup AWS Account
Expand Down Expand Up @@ -91,7 +102,7 @@ Success looks like this:
Failure like this
==> Builds finished but no artifacts were created.

It can beneficial to check the logs before all the AMIs are completed,
It can be beneficial to check the logs before all the AMIs are completed,
when issues do occur, they frequently fail early. Discovering this
allows you to relauch packer.py in another terminal for the failed AMIs,
saving time overall.
Expand Down
9 changes: 5 additions & 4 deletions lib/cloudformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ def add_nat(self, key, subnet, depends_on=None):
}
}

def add_ec2_instance(self, key, hostname, ami, keypair, subnet=Ref("Subnet"), type_="t2.micro", iface_check=True, public_ip=False, security_groups=None, user_data=None, meta_data=None, role=None, depends_on=None):
def add_ec2_instance(self, key, hostname, ami, keypair, subnet=Ref("Subnet"), type_="t3.micro", iface_check=True, public_ip=False, security_groups=None, user_data=None, meta_data=None, role=None, depends_on=None):
"""Add an EC2 instance to the configuration

Args:
Expand Down Expand Up @@ -1046,7 +1046,7 @@ def add_ec2_instance(self, key, hostname, ami, keypair, subnet=Ref("Subnet"), ty
self.keypairs[hostname] = keypair
self._add_record_cname(key, hostname, ec2 = True)

def add_rds_db(self, key, hostname, port, db_name, username, password, subnets, type_="db.t2.micro", storage="5", security_groups=None):
def add_rds_db(self, key, hostname, port, db_name, username, password, subnets, rds_engine_version="8.0.40", type_="db.t2.micro", storage="5", security_groups=None):
"""Add an RDS DB instance to the configuration

Args:
Expand All @@ -1058,6 +1058,7 @@ def add_rds_db(self, key, hostname, port, db_name, username, password, subnets,
password (str) : The (plaintext) password for the master username
subnets (list) : A list of Subnet IDs or Refs across which
to create a DB SubnetGroup for the DB Instance to launch into
rds_engine_version (str) : Engine Version of the RDS Database
type_ (str) : The RDS instance type to create
storage (int|string) : The storage size of the database (in GB)
security_groups (None|list) : A list of SecurityGroup IDs or Refs
Expand All @@ -1070,7 +1071,7 @@ def add_rds_db(self, key, hostname, port, db_name, username, password, subnets,
"Properties" : {
"Engine" : "mysql",
"LicenseModel" : "general-public-license",
"EngineVersion" : "5.7.39", # was 5.6.48
"EngineVersion" : rds_engine_version,
"DBInstanceClass" : type_,
"MultiAZ" : "true",
"StorageType" : "standard",
Expand Down Expand Up @@ -1946,7 +1947,7 @@ def append_s3_bucket_policy(self, key, bucket_name, action, principal, bucket_on
})


def add_lambda(self, key, name, role, file=None, handler=None, s3=None, description="", memory=128, timeout=3, security_groups=None, subnets=None, depends_on=None, runtime="python3.7", reserved_executions=None, dlq=None, layers=None):
def add_lambda(self, key, name, role, file=None, handler=None, s3=None, description="", memory=128, timeout=3, security_groups=None, subnets=None, depends_on=None, runtime="python3.11", reserved_executions=None, dlq=None, layers=None):
"""Create a Python Lambda

Args:
Expand Down
2 changes: 2 additions & 0 deletions lib/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class BossConfiguration(object):
'SCENARIO', # Optional, no default
'VERIFY_SSL', # Optional
'AUTH_RDS',
'RDS_ENGINE_VERSION', # Optional
'LAMBDA_BUCKET',
'LAMBDA_SERVER',
'LAMBDA_SERVER_KEY',
Expand Down Expand Up @@ -96,6 +97,7 @@ class BossConfiguration(object):
'SLACK_WEBHOOK_HOST': 'hooks.slack.com',
'SLACK_WEBHOOK_PATH_DYNAMODB_AUTOSCALE': None,
'DYNAMODB_AUTOSCALE_PROVISIONER': 'BossDefaultProvisioners',
'RDS_ENGINE_VERSION': "8.0.35"
}

def __init__(self, bosslet, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion lib/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def repo_path(*args):
########################
# Service Check Timeouts
TIMEOUT_VAULT = 120
TIMEOUT_KEYCLOAK = 150
TIMEOUT_KEYCLOAK = 180
AUTH_HEALTH_CHECK_GRACE_PERIOD = 160


Expand Down
3 changes: 2 additions & 1 deletion lib/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .exceptions import SSHError
from .names import AWSNames


def gen_timeout(total, step):
"""Break the total timeout value into steps
that are a specific size.
Expand All @@ -44,6 +45,7 @@ def gen_timeout(total, step):
rtn.insert(0, remainder) # Sleep for the partial time first
return rtn


class ExternalCalls:
"""Class that helps with forming connections from the local machine to machines
within a VPC through the VPC's bastion machine.
Expand Down Expand Up @@ -231,7 +233,6 @@ def check_vault(self, timeout, exception=True):
print("Error establishing SSH tunnel to Vault, waiting")
time.sleep(error_sleep)


def check_keycloak(self, timeout, exception=True):
"""Keycloak status check to see if Keycloak is accessible
"""
Expand Down
19 changes: 17 additions & 2 deletions lib/keycloak.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import json
import ssl
from pprint import pprint

from urllib.request import Request, urlopen
from urllib.parse import urlencode
from urllib.error import HTTPError
Expand Down Expand Up @@ -122,6 +124,10 @@ def login(self, username=None, password=None, client_id=None):
if client_id is None:
raise Exception("No client_id set")

print(f"username: '{username}'")
print(f"password: '{password}'")
print(f"client_id: '{client_id}'")

self.token = self.request(
"/auth/realms/master/protocol/openid-connect/token",
params={
Expand All @@ -136,8 +142,12 @@ def login(self, username=None, password=None, client_id=None):
)

if self.token is None:
#print("Could not authenticate to KeyCloak Server")
print("Could not authenticate to KeyCloak Server.")
raise exceptions.KeyCloakLoginError(self.url_base, username)
else:
# TODO SH After Debug remove these if appropriate
print("Keycloak token received after login.")
pprint(self.token)

return self # DP NOTE: So context manager works correctly

Expand All @@ -150,7 +160,7 @@ def logout(self):
if self.token is None:
return

self.request( # no response
logout_response = self.request( # no response
"/auth/realms/master/protocol/openid-connect/logout",
params={
"refresh_token": self.token["refresh_token"],
Expand All @@ -161,11 +171,16 @@ def logout(self):
}
)

# TODO SH Delete debug statements
print("response from keycloak logout")
pprint(logout_response)

self.token = None

def __enter__(self):
"""The start of the context manager, which handles automatically calling logout."""
if self.token is None:
print("Keycloak token is none, logging into keycloak")
self.login()
return self

Expand Down
Loading