Skip to content

Commit 0b39ce8

Browse files
committed
automate s3 creds
1 parent 0b24cd8 commit 0b39ce8

File tree

2 files changed

+73
-51
lines changed

2 files changed

+73
-51
lines changed

docs/opentofu-remote-state.md

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ but includes some missing details and is modified for common appliance workflows
3535
cp environments/site/tofu/example-backends/gitlab.tf environments/$ENV/tofu
3636
```
3737

38-
2. Modify `environments/$ENV/tofu/gitlab.tf` file to set the default for the
38+
2. Modify `environments/$ENV/tofu/gitlab.tf` to set the default for the
3939
project ID. This can be found by clicking the 3-dot menu at the top right of
4040
the GitLab project page.
4141

@@ -103,80 +103,76 @@ If the project token expires repeat the per-checkout configuration, but using
103103
## S3
104104

105105
For clouds with S3-compatible object storage (e.g. Ceph with [radosgw](https://docs.ceph.com/en/latest/radosgw/))
106-
the S3 backend can be used. This approach uses a bucket per environment.
106+
the S3 backend can be used. This approach uses a bucket per environment and
107+
derives credentials from OpenStack credentials, meaning no backend-specific
108+
per-checkout configuration is required.
107109

108-
With the environment activated:
110+
### Initial setup
109111

110-
1. Create a bucket:
112+
1. Create an S3 bucket matching the current environment name:
111113

112114
```shell
113-
export TF_STATE_NAME="$(basename $APPLIANCES_ENVIRONMENT_ROOT)"
114-
openstack container create $TF_STATE_NAME
115+
openstack container create $(basename $APPLIANCES_ENVIRONMENT_ROOT)
116+
```
115117

116-
2. Create credentials:
118+
2. Create `ec2` credentials:
117119

118120
```shell
119121
openstack ec2 credentials create
120122
```
121-
122-
From the returned values, set:
123123

124-
```shell
125-
export AWS_ACCESS_KEY_ID= # "access" value
126-
export AWS_SECRET_ACCESS_KEY= # "secret" value
127-
```
124+
and make a note of the `access` field returned.
128125

129-
Note these are available any time by running:
126+
3. Create the backend file:
130127

131128
```shell
132-
openstack ec2 credentials list
129+
cp environments/site/tofu/example-backends/s3.tf environments/$ENV/tofu
133130
```
134131

135-
TODO: Think about automating these into the activate script??
132+
4. Modify `environments/$ENV/tofu/s3.tf` to set the default for `s3_backend_endpoint`.
133+
This is the radosgw address. If not known it can be determined by creating a
134+
public bucket, and then getting the URL using
135+
Project > Containers > (your public bucket) > Link
136+
which provides an URL of the form `https://$ENDPOINT/swift/...`.
136137

137-
3. Create a backend file and commit it, for example:
138+
5. Add the following to `environments/$ENV/activate`:
138139

139-
```terraform
140-
# environments/$ENV/tofu/backend.tf:
141-
terraform {
142-
backend "s3" {
143-
endpoint = "leafcloud.store"
144-
bucket = "$ENV" # ** replace with environment name **
145-
key = "environment.tfstate"
146-
region = "dummy"
147-
148-
skip_region_validation = true
149-
skip_credentials_validation = true
150-
force_path_style = true
151-
}
152-
}
140+
```bash
141+
export AWS_ACCESS_KEY_ID=$EC2_CREDENTIALS_ACCESS
142+
export AWS_SECRET_ACCESS_KEY=$(openstack ec2 credentials show $AWS_ACCESS_KEY_ID -f value -c secret)
153143
```
144+
145+
replacing `$EC2_CREDENTIALS_ACCESS` with the `access` field of the created
146+
credentials.
147+
148+
This avoids these credentials being persisted in local files.
149+
150+
6. Copy the lines above into your shell to set them for your current shell.
154151

155-
Note that:
156-
- `endpoint` is the radosgw address. If not known this can be determined by
157-
creating a public bucket, and then getting the URL using
158-
Project > Containers > (your public container) > Link, which provides an
159-
URL of the form `https://$ENDPOINT/swift/...`.
160-
`/swift`.
161-
- `region` is required but not used in radosgw, hence `skip_region_validation`.
162-
- `key` is an arbitrary state file name
163-
- `skip_credentials_validation`: Disables STS - this may or may not be
164-
required depending on the radosgw configuration.
165-
- `force_path_style`: May or may not be required depending on the radosgw
166-
configuration.
167-
168-
4. Run:
152+
7. With the environment activated, initialise OpenTofu.
169153

154+
If no local state exists run:
155+
170156
```shell
157+
cd environments/$ENV/tofu/
171158
tofu init
172159
```
160+
161+
otherwise append `-migrate-state` to the `init` command to attempt to copy
162+
local state to the new backend.
173163

174-
OpenTofu is now configured to use the cloud's S3 to store state for this
175-
environment.
164+
8. If this fails, try setting `use_path_style = true` in `environments/$ENV/tofu/s3.tf`.
176165

166+
9. Once it works, commit `environments/$ENV/tofu/s3.tf` and `environments/$ENV/activate`.
177167

178-
TODO: consider bucket versioning??
179-
TODO: consider whether we should use a single bucket for both stg and prd to make
180-
testing better??
168+
OpenTofu is now configured to use the cloud's S3-compatible storage to store
169+
state for this environment.
170+
171+
Repeat for each environment needing remote state.
172+
173+
For more configuration options, see the OpenTofu [s3 backend docs](https://opentofu.org/docs/language/settings/backends/s3/).
174+
175+
### Per-checkout configuration
181176
182-
TODO: understand -reconfigure vs -migrate-state?
177+
The ec2 credentials will automatically be loaded when activating the environment.
178+
For a new checkout simply initialise OpenTofu as normal as described in step 7 above.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
variable "s3_backend_endpoint" {
2+
type = string
3+
description = "radosgw address without protocol or path e.g. leafcloud.store"
4+
default = # Set this here
5+
}
6+
7+
variable "s3"
8+
9+
terraform {
10+
backend "s3" {
11+
endpoint = var.s3_backend_endpoint
12+
bucket = basename(var.environment_root)
13+
key = "environment.tfstate"
14+
15+
# Reginon is required but not used in radosgw:
16+
region = "dummy"
17+
skip_region_validation = true
18+
19+
# Normally STS is not configured in radosgw:
20+
skip_credentials_validation = true
21+
22+
# Enable path-style S3 URLs (https://<HOST>/<BUCKET> instead of https://<BUCKET>.<HOST>)
23+
# may or may not be required depending on radosgw configuration
24+
use_path_style = true
25+
}
26+
}

0 commit comments

Comments
 (0)