Skip to content

Commit

Permalink
Merge pull request #44 from IBM/app-on-boarding
Browse files Browse the repository at this point in the history
Script to help on-boarding application, containerized several scripts, added pod and daemonset examples, redesigned policy format
  • Loading branch information
mrsabath authored Jun 16, 2020
2 parents 99b630b + 6a47a4b commit 5da327b
Show file tree
Hide file tree
Showing 34 changed files with 1,070 additions and 323 deletions.
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ To run a full build that compiles the code, builds images and creates helm packa
./buildTSI.sh
```

If you have credentials to push the image into Docker Hub:

```console
./buildTSI.sh push
```

When pushing the images to the registry, the user has to be logged in to Docker Hub with permissions to push images to `hub.docker.com/repository/docker/trustedseriviceidentity`. Make sure you are part of the Organization: [https://hub.docker.com/orgs/trustedseriviceidentity](https://hub.docker.com/orgs/trustedseriviceidentity)

or if you like to build individual components:
Expand Down
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,16 @@ At this point, this is an expected result.
The following information is required to deploy TSI node-setup helm chart:
* cluster name - name of the cluster. This must correspond to the actual name of the cluster
* cluster region - label associated with the actual region for the data center (e.g. eu-de, us-south, eu-gb)
When using IKS, these values can be obtain via a script:

```console
examples/vault/demo.get-cluster-info.sh

export CLUSTER_NAME=ti-test1
export REGION=eu-de
```
Then use the provided output to setup env. variables to be used later.

TSI currently supports 2 methods for signing JWT Tokens:
* using TPM2 - private keys are obtained directly from TPM using TPM wrapper (VTPM2)
* using custom signing service JSS (JWT Signing Service)
Expand All @@ -220,23 +230,22 @@ To use vTPM, deploy TSI Node Setup helm charts with all the functions disabled.
Replace X.X.X with a proper version numbers (typically the highest, the most recent).
```console
helm install charts/tsi-node-setup-X.X.X --debug --name tsi-setup --set reset.all=false \
--set reset.x5c=false --set cluster.name=CLUSTER_NAME --set cluster.region=CLUSTER_REGION
--set reset.x5c=false --set cluster.name=$CLUSTER_NAME --set cluster.region=$REGION
```

In order to run JSS server, all worker nodes have to be setup with private keys. This operation needs to be executed only once.
If you are running this setup for the first time or like to override previous setup values, execute the helm command below.



```console
helm install charts/tsi-node-setup-X.X.X --debug --name tsi-setup --set reset.all=true \
--set cluster.name=CLUSTER_NAME --set cluster.region=CLUSTER_REGION
--set cluster.name=$CLUSTER_NAME --set cluster.region=$REGION
```

To keep the existing private key, but just reset the intermediate CA (`x5c`)
```console
helm install charts/tsi-node-setup-X.X.X --debug --name tsi-setup --set reset.x5c=true \
--set cluster.name=CLUSTER_NAME --set cluster.region=CLUSTER_REGION
--set cluster.name=$CLUSTER_NAME --set cluster.region=$REGION
```

Once the worker nodes are setup, deploy the TSI environment
Expand All @@ -263,8 +272,8 @@ Replace X.X.X with a proper version numbers (typically the highest, the most rec
```console
export VAULT_ADDR=http://<vault_location>
helm install charts/ti-key-release-2-X.X.X.tgz --debug --name tsi \
--set ti-key-release-1.cluster.name=CLUSTER_NAME \
--set ti-key-release-1.cluster.region=CLUSTER_REGION \
--set ti-key-release-1.cluster.name=$CLUSTER_NAME \
--set ti-key-release-1.cluster.region=$REGION \
--set ti-key-release-1.vaultAddress=$VAULT_ADDR \
--set jssService.type=jss-server
```
Expand Down
1 change: 1 addition & 0 deletions buildTSI.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ run() {

run "make $ALL$PUSH"
run "make $ALL$PUSH -C components/jss/"
run "make $ALL$PUSH -C components/tsi-util/"
run "make $ALL$PUSH -C components/vtpm2-server/"
run "make $ALL$PUSH -C components/jwt-sidecar/"
run "make $ALL$PUSH -C components/node-setup/"
Expand Down
Binary file added charts/ti-key-release-2-v1.7.0.tgz
Binary file not shown.
10 changes: 8 additions & 2 deletions charts/ti-key-release-2/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ This helm chart installs environment for Trusted Identity
# however, there is a problem with retrieving values that contain "-"
# see the helm issue: https://github.com/helm/helm/issues/2192
This chart tiVersion: {{ .Chart.AppVersion }}

vaultAddress: {{ index .Values "ti-key-release-1" "vaultAddress" }}
cluster.name: {{ index .Values "ti-key-release-1" "cluster" "name" }}
cluster.region: {{ index .Values "ti-key-release-1" "cluster" "region" }}
jwt.expireSec: {{ index .Values "ti-key-release-1" "jwt" "expireSec" }}
secrets.refreshSec: {{ index .Values "ti-key-release-1" "secrets" "refreshSec" }}
jssService.type: {{ .Values.jssService.type }}

To execute a test, create a new namespace then deploy the test application:
To execute a test, create a new namespace, load the application secrets to vault,
then deploy the test application:

kubectl create ns test
examples/vault/demo.secret-maker.sh -f examples/myubuntu.yaml -n test > myubuntu.secrets.sh
# update the myubuntu
chmod + myubuntu.secrets.sh
./myubuntu.secrets.sh
kubectl create -f examples/myubuntu.yaml -n test
Then check if the secret is available:
kubectl -n test exec -it $(k -n test get pods | grep myubuntu | awk '{print $1}' ) cat /tsi-secrets/mysecrets/mysecret4
Binary file added charts/tsi-node-setup-v1.7.0.tgz
Binary file not shown.
2 changes: 1 addition & 1 deletion components/jss/web-server-priv.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ def get():
return str(out)
except Exception as e:
print e.output
return "",503
return "",403
10 changes: 5 additions & 5 deletions components/jwt-sidecar/get-vault-secrets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ HELPMEHELPME
# run secret retrieval and output results to specified location
run()
{
# SECNAME=${SECNAME}, CONSTRAINS=${CONSTR}, LOCPATH=${LOCPATH}
# SECNAME=${SECNAME}, CONSTRAINTS=${CONSTR}, LOCPATH=${LOCPATH}
local SECNAME=$1
local CONSTR=$2
local LOCPATH=$3
Expand All @@ -91,7 +91,7 @@ run()
# 2. Using claims associated with the Role, build the Vault Path to the
# given secret.

# convert CONSTRAINS into Vault Roles and Vault Paths:
# convert CONSTRAINTS into Vault Roles and Vault Paths:
ROLE=
VAULT_PATH=

Expand Down Expand Up @@ -119,7 +119,7 @@ run()
ROLE="tsi-role-rcni"
VAULT_PATH="secret/tsi-rcni"
;;
*) echo "# ERROR: invalid constrains requested: ${CONSTR}"
*) echo "# ERROR: invalid constraints requested: ${CONSTR}"
return 1
;;
esac
Expand Down Expand Up @@ -193,13 +193,13 @@ run()
for row in $(echo "${JSON}" | jq -c '.[]' ); do
# for each requested secret parse its attributes
SECNAME=$(echo "$row" | jq -r '."tsi.secret/name"')
CONSTR=$(echo "$row" | jq -r '."tsi.secret/constrains"')
CONSTR=$(echo "$row" | jq -r '."tsi.secret/constraints"')
LOCPATH=$(echo "$row" | jq -r '."tsi.secret/local-path"')

# then run secret retrieval from Vault
run "$SECNAME" "$CONSTR" "$LOCPATH"
RT=$?
if [ "$RT" != "0" ]; then
echo "Error processing secret SECNAME=${SECNAME}, CONSTRAINS=${CONSTR}, LOCPATH=${LOCPATH}"
echo "Error processing secret SECNAME=${SECNAME}, CONSTRAINTS=${CONSTR}, LOCPATH=${LOCPATH}"
fi
done
7 changes: 0 additions & 7 deletions components/node-setup/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@ RUN cd /usr/local/bin && \

COPY init-node.sh /usr/local/bin/


# Default values for JWT, issuer and token expiration in seconds
#ARG DEFAULT_ISS="wsched@us.ibm.com"
#ARG DEFAULT_TTL_SEC=30
#ENV ISS=${DEFAULT_ISS}
#ENV TTL_SEC=${DEFAULT_TTL_SEC}

ARG DEFAULT_PRIVATE_DIR="/host/tsi-secure"
ENV PRIVATEDIR=${DEFAULT_PRIVATE_DIR}

Expand Down
28 changes: 28 additions & 0 deletions components/tsi-util/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM ubuntu:18.04
RUN apt update && \
apt install -y wget unzip && \
apt install -y curl jq vim && \
apt install -y openssl

# install yq required for xform YAML to JSON
RUN apt-get install -y software-properties-common && \
add-apt-repository ppa:rmescandon/yq && \
apt update && apt install -y yq

RUN cd /usr/local/bin && \
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
chmod +x kubectl

RUN wget https://releases.hashicorp.com/vault/1.4.2/vault_1.4.2_linux_amd64.zip && \
unzip vault_1.4.2_linux_amd64.zip && \
mv vault /usr/local/bin/ && \
rm -f vault_1.4.2_linux_amd64.zip

COPY secret-maker.sh /usr/local/bin/
COPY getClusterInfo.sh /usr/local/bin/
COPY load-sample-policies.sh /usr/local/bin/
COPY vault-tpl/ /vault-tpl
COPY vault-setup.sh /usr/local/bin/

# run it forever
CMD ["/bin/bash", "-c", "tail -f /dev/null"]
36 changes: 36 additions & 0 deletions components/tsi-util/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
TSI_VERSION=$(shell cat ../../tsi-version.txt)
GIT_COMMIT_SHA="$(shell git rev-parse --short HEAD 2>/dev/null)"
GIT_REMOTE_URL="$(shell git config --get remote.origin.url 2>/dev/null)"
BUILD_DATE="$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")"
BINARY_NAME="tsi-util"
REPO ?= trustedseriviceidentity
IMAGE := $(REPO)/$(BINARY_NAME):$(GIT_COMMIT_SHA)
MUTABLE_IMAGE := $(REPO)/$(BINARY_NAME):$(TSI_VERSION)
LATEST := $(REPO)/$(BINARY_NAME):latest

all: docker timestamp

allpush: docker docker-push timestamp

fastpush: fast docker-push timestamp

fast:
docker build -t $(IMAGE) .
docker tag $(IMAGE) $(MUTABLE_IMAGE)
docker tag $(IMAGE) $(LATEST)
date

docker:
docker build --no-cache -t $(IMAGE) .
docker tag $(IMAGE) $(MUTABLE_IMAGE)
docker tag $(IMAGE) $(LATEST)

docker-push:
docker push $(IMAGE)
docker push $(MUTABLE_IMAGE)
docker push $(LATEST)

timestamp:
date

.PHONY: all fast allpush fastpush docker docker-push timestamp
45 changes: 45 additions & 0 deletions components/tsi-util/getClusterInfo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

## create help menu:
helpme()
{
cat <<HELPMEHELPME
This script returns cluster information
syntax:
$0 [cluster-info.yaml]
where:
[cluster-info.yaml] - cluster info, otherwise defaults to '/tmp/clusterinfo'
HELPMEHELPME
}

# validate the input arguments
if [[ "$1" == "-?" || "$1" == "-h" || "$1" == "--help" ]] ; then
helpme
exit 1
fi

if [[ "$1" == "" ]] ; then
CLUSTER_YAML="/tmp/clusterinfo"
else
CLUSTER_YAML="$1"
fi


### Get Cluter Information

# extract cluster and region info from provided data
CLYM1="/tmp/cl1.$$"
cat ${CLUSTER_YAML} > ${CLYM1}
CLJS1=$(yq r -j ${CLYM1} |jq -r '.data."cluster-config.json"')
rm "${CLYM1}"
CLUSTER=$(echo "$CLJS1" | jq -r '.name')
# DC=$(echo "$CLJS1" | jq -r '.datacenter')

# Confirmed with Armada team that CRN format should stay consistent for a while
# CRN format example:
# crn:v1:bluemix:public:containers-kubernetes:eu-de:586283a9abda5102d46e1b94b923a6c5:5f4306a2738d4cdd89ff067c9481555e
REGION=$(echo "$CLJS1" | jq -r '."crn"' | cut -d":" -f6)
echo "export CLUSTER_NAME=$CLUSTER"
echo "export REGION=$REGION"
# echo "export DATA_CENTER=$DC"
88 changes: 88 additions & 0 deletions components/tsi-util/load-sample-policies.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash

# Trusted Service Identiy plugin name
export PLUGIN="vault-plugin-auth-ti-jwt"

## create help menu:
helpme()
{
cat <<HELPMEHELPME
Syntax: ${0} <vault_addr> <vault_token>
Where:
vault_addr - vault address (or ingress) in format http://vault.server:8200
token - vault root token to setup the plugin
Or make sure ROOT_TOKEN and VAULT_ADDR are set as environment variables.
export ROOT_TOKEN=
export VAULT_ADDR=(vault address in format http://vault.server:8200)
HELPMEHELPME
}

loadVault()
{
#docker run -d --name=dev-vault -v ${PWD}/local.json:/vault/config/local.json -v ${PWD}/pkg/linux_amd64/${PLUGIN}:/plugins/${PLUGIN} -p 127.0.0.1:8200:8200/tcp vault
# echo "Root Token: ${ROOT_TOKEN}"
vault login -no-print ${ROOT_TOKEN}
RT=$?

if [ $RT -ne 0 ] ; then
echo "Vault login failed!"
exit 1
fi

export MOUNT_ACCESSOR=$(curl --header "X-Vault-Token: ${ROOT_TOKEN}" --request GET ${VAULT_ADDR}/v1/sys/auth | jq -r '.["trusted-identity/"].accessor')

# Use policy templates to create policy files.
# The example below uses 4 different policies with the following constraints:
# - rcni - uses region, cluster-name, namespace and images
# - rcn - uses region, cluster-name, namespace
# - ri - uses region and images
# - r - uses region only

# replace mount accessor in policy
sed "s/<%MOUNT_ACCESSOR%>/$MOUNT_ACCESSOR/g" /vault-tpl/tsi-policy.rcni.hcl.tpl > /vault-tpl/tsi-policy.rcni.hcl
sed "s/<%MOUNT_ACCESSOR%>/$MOUNT_ACCESSOR/g" /vault-tpl/tsi-policy.rcn.hcl.tpl > /vault-tpl/tsi-policy.rcn.hcl
sed "s/<%MOUNT_ACCESSOR%>/$MOUNT_ACCESSOR/g" /vault-tpl/tsi-policy.ri.hcl.tpl > /vault-tpl/tsi-policy.ri.hcl
sed "s/<%MOUNT_ACCESSOR%>/$MOUNT_ACCESSOR/g" /vault-tpl/tsi-policy.r.hcl.tpl > /vault-tpl/tsi-policy.r.hcl

# write policy to grant access to secrets
vault policy write tsi-policy-rcni /vault-tpl/tsi-policy.rcni.hcl
vault policy read tsi-policy-rcni
vault policy write tsi-policy-rcn /vault-tpl/tsi-policy.rcn.hcl
vault policy read tsi-policy-rcn
vault policy write tsi-policy-ri /vault-tpl/tsi-policy.ri.hcl
vault policy read tsi-policy-ri
vault policy write tsi-policy-r /vault-tpl/tsi-policy.r.hcl
vault policy read tsi-policy-r

# create role to associate policy with login
# we choosed to use one role, one policy association
# *NOTE* the first role MUST include all the metadata that would be used by other roles/policies, not only the first one.
vault write auth/trusted-identity/role/tsi-role-rcni bound_subject="wsched@us.ibm.com" user_claim="pod" metadata_claims="region,cluster-name,namespace,images" policies=tsi-policy-rcni
vault read auth/trusted-identity/role/tsi-role-rcni

vault write auth/trusted-identity/role/tsi-role-rcn bound_subject="wsched@us.ibm.com" user_claim="pod" metadata_claims="region,cluster-name,namespace" policies=tsi-policy-rcn
vault read auth/trusted-identity/role/tsi-role-rcn

vault write auth/trusted-identity/role/tsi-role-ri bound_subject="wsched@us.ibm.com" user_claim="pod" metadata_claims="region,images" policies=tsi-policy-ri
vault read auth/trusted-identity/role/tsi-role-ri

vault write auth/trusted-identity/role/tsi-role-r bound_subject="wsched@us.ibm.com" user_claim="pod" metadata_claims="region" policies=tsi-policy-r
vault read auth/trusted-identity/role/tsi-role-r
}

# validate the arguments
if [[ "$1" != "" && "$2" != "" ]] ; then
export VAULT_ADDR="$1"
export ROOT_TOKEN="$2"
fi

if [[ "$ROOT_TOKEN" == "" || "$VAULT_ADDR" == "" ]] ; then
echo "ROOT_TOKEN and VAULT_ADDR must be set"
helpme
exit 1
else
loadVault
fi
Loading

0 comments on commit 5da327b

Please sign in to comment.