Skip to content

Commit 27d9b60

Browse files
authored
feat: Add action (#1)
* feat: Add action * docs: Automated README update
1 parent 62282a9 commit 27d9b60

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,60 @@
11
<!-- action-docs-all source="action.yml" project="bendwyer/action-rotate-hcp-terraform-user-token" version="v1" -->
2+
## action-rotate-hcp-terraform-user-token
23

4+
### Description
5+
6+
Rotates a HCP Terraform user token stored as a secret in a GitHub repository.
7+
8+
### Inputs
9+
10+
| name | description | required | default |
11+
| --- | --- | --- | --- |
12+
| `github_token` | <p>GitHub token used for writing the HCP Terraform user token to the repository secret store.</p> | `false` | `${{ github.token }}` |
13+
| `github_secrets_name` | <p>Name of the secret in the repository secret store where the token will be written.</p> | `false` | `HCP_TERRAFORM_USER_TOKEN` |
14+
| `hcp_terraform_user_token` | <p>HCP Terraform user token to be rotated. This token must already exist and be saved as a repository secret before running this action.</p> | `true` | `""` |
15+
| `hcp_terraform_user_token_description` | <p>Description for the HCP Terraform user token. Must be the same for the original and new tokens.</p> | `false` | `github-token` |
16+
| `hcp_terraform_user_token_expiration` | <p>Time in days when the HCP Terraform user token will expire.</p> | `false` | `30` |
17+
18+
19+
### Runs
20+
21+
This action is a `composite` action.
22+
23+
### Usage
24+
25+
```yaml
26+
- uses: bendwyer/action-rotate-hcp-terraform-user-token@v1
27+
with:
28+
github_token:
29+
# GitHub token used for writing the HCP Terraform user token to the repository secret store.
30+
#
31+
# Required: false
32+
# Default: ${{ github.token }}
33+
34+
github_secrets_name:
35+
# Name of the secret in the repository secret store where the token will be written.
36+
#
37+
# Required: false
38+
# Default: HCP_TERRAFORM_USER_TOKEN
39+
40+
hcp_terraform_user_token:
41+
# HCP Terraform user token to be rotated. This token must already exist and be saved as a repository secret before running this action.
42+
#
43+
# Required: true
44+
# Default: ""
45+
46+
hcp_terraform_user_token_description:
47+
# Description for the HCP Terraform user token. Must be the same for the original and new tokens.
48+
#
49+
# Required: false
50+
# Default: github-token
51+
52+
hcp_terraform_user_token_expiration:
53+
# Time in days when the HCP Terraform user token will expire.
54+
#
55+
# Required: false
56+
# Default: 30
57+
```
358
<!-- action-docs-all source="action.yml" project="bendwyer/action-rotate-hcp-terraform-user-token" version="v1" -->
459

560
Resources

action.yml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
name: action-rotate-hcp-terraform-user-token
3+
description: Rotates a HCP Terraform user token stored as a secret in a GitHub repository.
4+
author: Ben Dwyer (github.com/bendwyer)
5+
6+
inputs:
7+
github_token:
8+
description: GitHub token used for writing the HCP Terraform user token to the repository secret store.
9+
required: false
10+
default: ${{ github.token }}
11+
github_secrets_name:
12+
description: Name of the secret in the repository secret store where the token will be written.
13+
required: false
14+
default: HCP_TERRAFORM_USER_TOKEN
15+
hcp_terraform_user_token:
16+
description: HCP Terraform user token to be rotated. This token must already exist and be saved as a repository secret before running this action.
17+
required: true
18+
hcp_terraform_user_token_description:
19+
description: Description for the HCP Terraform user token. Must be the same for the original and new tokens.
20+
required: false
21+
default: github-token
22+
hcp_terraform_user_token_expiration:
23+
description: Time in days when the HCP Terraform user token will expire.
24+
default: "30"
25+
26+
runs:
27+
using: composite
28+
steps:
29+
- name: Rotate HCP Terraform user token
30+
env:
31+
GH_TOKEN: ${{ inputs.github_token }}
32+
run: |
33+
echo "Set token"
34+
TOKEN=${{ inputs.hcp_terraform_user_token }}
35+
echo "Mask token"
36+
echo "::add-mask::$TOKEN"
37+
echo "Set token description"
38+
TOKEN_DESCRIPTION=${{ inputs.hcp_terraform_user_token_description }}
39+
echo "Set expiration"
40+
TOKEN_EXPIRATION=${{ inputs.hcp_terraform_user_token_expiration }}
41+
SECRETS_NAME=${{ inputs.github_secrets_name }}
42+
echo "Set user ID"
43+
ID=$(curl -Ss --fail-with-body --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/vnd.api+json" --request GET https://app.terraform.io/api/v2/account/details | jq -r '.data.id')
44+
echo "Check if date should be calculated"
45+
if [[ -n $TOKEN_EXPIRATION ]];
46+
then
47+
echo "Calculate date"
48+
DATE=$(date -d "+$TOKEN_EXPIRATION days" -u +%Y-%m-%dT%H:%M:%S.%3NZ)
49+
fi
50+
echo "Get all token info"
51+
ALL_TOKENS=$(curl -Ss --fail-with-body --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/vnd.api+json" --request GET https://app.terraform.io/api/v2/users/$ID/authentication-tokens)
52+
echo "Filter matched token info"
53+
MATCHED_TOKEN_INFO=$(echo $ALL_TOKENS | jq -r --arg TOKEN_DESCRIPTION "$TOKEN_DESCRIPTION" --arg DATE "$DATE" '[.data[] | {id,attributes} | select(.attributes.description==$TOKEN_DESCRIPTION) | select(.attributes."expired-at"!=$DATE)]')
54+
echo "Get matched token IDs"
55+
MATCHED_TOKEN_IDS=$(echo $MATCHED_TOKEN_INFO | jq -c 'map(.id)')
56+
echo "Get matched token count"
57+
MATCHED_TOKEN_COUNT=$(echo $MATCHED_TOKEN_INFO | jq -c 'map(.id) | length')
58+
if [[ $MATCHED_TOKEN_COUNT -ge 2 ]]
59+
then
60+
echo "ERROR: $MATCHED_TOKEN_COUNT tokens matched search criteria. Please ensure that 0 or 1 tokens match the search criteria." >> /dev/stderr
61+
exit 1
62+
else
63+
echo "Matched token IDs: $MATCHED_TOKEN_IDS"
64+
echo "Matched token count: $MATCHED_TOKEN_COUNT"
65+
fi
66+
echo "Create json payload"
67+
PAYLOAD=$(cat <<EOF
68+
{
69+
"data": {
70+
"type": "authentication-tokens",
71+
"attributes": {
72+
"description":"$TOKEN_DESCRIPTION",
73+
"expired-at": "$DATE"
74+
}
75+
}
76+
}
77+
EOF
78+
)
79+
echo "Compress payload"
80+
PAYLOAD_COMPRESSED=$(echo $PAYLOAD | jq -c)
81+
echo "Check if new user token should be created"
82+
if [[ $MATCHED_TOKEN_COUNT == 0 || $MATCHED_TOKEN_COUNT == 1 ]]
83+
then
84+
echo "Create new token"
85+
NEW_TOKEN=$(curl -Ss --fail-with-body --header "Authorization: Bearer $TOKEN" --header "Content-Type: application/vnd.api+json" --request POST --data $PAYLOAD_COMPRESSED https://app.terraform.io/api/v2/users/$ID/authentication-tokens | jq -r '.data.attributes.token')
86+
echo "Mask new token"
87+
echo "::add-mask::$NEW_TOKEN"
88+
echo "Write new token to repository secrets"
89+
gh secret set $SECRETS_NAME --body "$NEW_TOKEN" --app actions
90+
fi
91+
echo "Check if old user token should be deleted"
92+
if [[ $MATCHED_TOKEN_COUNT == 1 ]]
93+
then
94+
echo "Get matched token ID"
95+
MATCHED_TOKEN_ID=$(echo $MATCHED_TOKEN_IDS | jq -r '.[]')
96+
echo "Delete old user token"
97+
curl -Ss --fail-with-body --header "Authorization: Bearer $NEW_TOKEN" --header "Content-Type: application/vnd.api+json" --request DELETE "https://app.terraform.io/api/v2/authentication-tokens/$MATCHED_TOKEN_ID"
98+
fi
99+
shell: bash

0 commit comments

Comments
 (0)