Skip to content

Commit b5ee29d

Browse files
Benbentwoclaude
andcommitted
docs: update realm PRDs with validation and directory structure changes
- Replace sanitization with validation (error on invalid characters) - Update directory structure: ~/.config/atmos/{realm}/{cloud}/{provider}/ - All cloud providers now share common base path with realm as top-level - Add clear error examples for invalid realm values Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 889948d commit b5ee29d

File tree

2 files changed

+145
-89
lines changed

2 files changed

+145
-89
lines changed

docs/prd/auth-realm-architecture.md

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,32 @@ By default, the realm is automatically computed as the SHA256 hash (first 8 char
4545
### Realm Value Requirements
4646

4747
**Allowed characters:**
48-
- ASCII alphanumeric: `a-z`, `A-Z`, `0-9`
48+
- ASCII lowercase alphanumeric: `a-z`, `0-9`
4949
- Hyphen: `-`
5050
- Underscore: `_`
5151

52-
**Sanitization rules (for explicit values):**
53-
1. Replace disallowed characters with hyphen
54-
2. Collapse consecutive hyphens
55-
3. Trim leading/trailing non-alphanumeric characters
56-
4. Convert to lowercase
52+
**Validation rules (for explicit values):**
53+
1. Must contain only allowed characters (lowercase alphanumeric, hyphen, underscore)
54+
2. Must not be empty
55+
3. Must not start or end with hyphen or underscore
56+
4. Must not contain consecutive hyphens or underscores
5757
5. Maximum 64 characters
58+
6. Must not contain path traversal sequences (`/`, `\`, `..`)
59+
60+
**Error behavior:** Invalid realm values result in an immediate error with a clear message explaining what characters are allowed. No sanitization is performed—the user must provide a valid realm value.
61+
62+
**Example error:**
63+
```
64+
Error: Invalid realm value 'my/realm'
65+
66+
Realm values must contain only lowercase letters, numbers, hyphens, and underscores.
67+
The following characters are not allowed: /
68+
69+
Please update your auth.realm configuration or ATMOS_AUTH_REALM environment variable.
70+
```
5871

5972
**Security:**
60-
- Prevents path traversal attacks (no `/`, `\`, `..`)
73+
- Prevents path traversal attacks (validation rejects `/`, `\`, `..`)
6174
- Cross-platform filesystem compatibility
6275
- Deterministic output
6376

@@ -67,34 +80,42 @@ By default, the realm is automatically computed as the SHA256 hash (first 8 char
6780

6881
### Credential File Storage
6982

70-
The realm becomes the **top-level directory** under the cloud-specific base path:
83+
The realm becomes the **top-level directory** under the atmos base path, with cloud as the next level:
7184

7285
| Cloud | Current Path | With Realm |
7386
|-------|--------------|------------|
74-
| AWS | `~/.config/atmos/aws/{provider}/` | `~/.config/atmos/aws/{realm}/{provider}/` |
75-
| Azure | `~/.azure/atmos/{provider}/` | `~/.azure/atmos/{realm}/{provider}/` |
87+
| AWS | `~/.config/atmos/aws/{provider}/` | `~/.config/atmos/{realm}/aws/{provider}/` |
88+
| Azure | `~/.azure/atmos/{provider}/` | `~/.config/atmos/{realm}/azure/{provider}/` |
89+
90+
**Note:** All cloud providers now share the same base path (`~/.config/atmos/`) with realm as the top-level directory, followed by cloud type, then provider.
7691

7792
### Directory Structure
7893

7994
```
80-
~/.config/atmos/aws/
95+
~/.config/atmos/
8196
├── a1b2c3d4/ # Realm (auto-hash from Customer A's path)
82-
│ ├── aws-sso/
83-
│ │ ├── credentials # INI file with identity profiles
84-
│ │ └── config
85-
│ └── aws-user/
86-
│ ├── credentials
87-
│ └── config
97+
│ └── aws/
98+
│ ├── aws-sso/
99+
│ │ ├── credentials # INI file with identity profiles
100+
│ │ └── config
101+
│ └── aws-user/
102+
│ ├── credentials
103+
│ └── config
88104
89105
├── b5c6d7e8/ # Realm (auto-hash from Customer B's path)
90-
│ └── aws-sso/ # Same provider name, different realm
91-
│ ├── credentials
92-
│ └── config
106+
│ └── aws/
107+
│ └── aws-sso/ # Same provider name, different realm
108+
│ ├── credentials
109+
│ └── config
93110
94111
└── customer-acme/ # Realm (explicit config)
95-
└── aws-sso/
96-
├── credentials
97-
└── config
112+
├── aws/
113+
│ └── aws-sso/
114+
│ ├── credentials
115+
│ └── config
116+
└── azure/
117+
└── azure-cli/
118+
└── credentials
98119
```
99120

100121
### Keyring Storage
@@ -114,8 +135,8 @@ Keyring keys include realm prefix:
114135
When credentials are set up, file paths include the realm:
115136

116137
```bash
117-
AWS_SHARED_CREDENTIALS_FILE=~/.config/atmos/aws/a1b2c3d4/aws-sso/credentials
118-
AWS_CONFIG_FILE=~/.config/atmos/aws/a1b2c3d4/aws-sso/config
138+
AWS_SHARED_CREDENTIALS_FILE=~/.config/atmos/a1b2c3d4/aws/aws-sso/credentials
139+
AWS_CONFIG_FILE=~/.config/atmos/a1b2c3d4/aws/aws-sso/config
119140
```
120141

121142
---
@@ -139,7 +160,7 @@ manager.realm (stored in auth manager)
139160
│ └──► keyring key: "atmos:a1b2c3d4:core-root/terraform"
140161
141162
├──► awsFileManager.GetCredentialsPath(provider, realm)
142-
│ └──► ~/.config/atmos/aws/a1b2c3d4/aws-sso/credentials
163+
│ └──► ~/.config/atmos/a1b2c3d4/aws/aws-sso/credentials
143164
144165
└──► PostAuthenticateParams.Realm
145166
@@ -175,10 +196,12 @@ type RealmInfo struct {
175196
}
176197

177198
// GetRealm computes the realm with proper precedence.
178-
func GetRealm(configRealm, cliConfigPath string) RealmInfo
199+
// Returns error if explicit realm value contains invalid characters.
200+
func GetRealm(configRealm, cliConfigPath string) (RealmInfo, error)
179201

180-
// sanitize ensures realm values are filesystem-safe.
181-
func sanitize(input string) string
202+
// validate checks that a realm value contains only allowed characters.
203+
// Returns error describing invalid characters if validation fails.
204+
func validate(input string) error
182205
```
183206

184207
### Schema Changes
@@ -239,27 +262,29 @@ type PostAuthenticateParams struct {
239262

240263
```go
241264
// GetCredentialsPath returns path with realm as top-level directory.
242-
// Result: ~/.config/atmos/aws/{realm}/{provider}/credentials
265+
// Result: ~/.config/atmos/{realm}/aws/{provider}/credentials
243266
func (m *AWSFileManager) GetCredentialsPath(providerName, realm string) string {
244267
if realm != "" {
245-
return filepath.Join(m.baseDir, realm, providerName, "credentials")
268+
return filepath.Join(m.baseDir, realm, "aws", providerName, "credentials")
246269
}
247-
return filepath.Join(m.baseDir, providerName, "credentials")
270+
return filepath.Join(m.baseDir, "aws", providerName, "credentials")
248271
}
249272

250273
// GetConfigPath returns path with realm as top-level directory.
251-
// Result: ~/.config/atmos/aws/{realm}/{provider}/config
274+
// Result: ~/.config/atmos/{realm}/aws/{provider}/config
252275
func (m *AWSFileManager) GetConfigPath(providerName, realm string) string {
253276
if realm != "" {
254-
return filepath.Join(m.baseDir, realm, providerName, "config")
277+
return filepath.Join(m.baseDir, realm, "aws", providerName, "config")
255278
}
256-
return filepath.Join(m.baseDir, providerName, "config")
279+
return filepath.Join(m.baseDir, "aws", providerName, "config")
257280
}
258281
```
259282

283+
**Note:** The `baseDir` changes from `~/.config/atmos/aws` to `~/.config/atmos` since realm is now top-level.
284+
260285
**File:** `pkg/auth/cloud/azure/files.go`
261286

262-
Similar changes for Azure file manager.
287+
Similar changes for Azure file manager, using `"azure"` as the cloud subdirectory.
263288

264289
### Manager Changes
265290

@@ -314,7 +339,7 @@ func TerraformPreHook(atmosConfig *schema.AtmosConfiguration, stackInfo *schema.
314339

315340
| File | Change |
316341
|------|--------|
317-
| `pkg/auth/realm/realm.go` | **NEW** - Realm computation and sanitization |
342+
| `pkg/auth/realm/realm.go` | **NEW** - Realm computation and validation |
318343
| `pkg/schema/schema_auth.go` | Add `Realm` field to `AuthConfig` |
319344
| `pkg/auth/types/interfaces.go` | Update `CredentialStore` interface, `PostAuthenticateParams` |
320345
| `pkg/auth/types/whoami.go` | Add `Realm`, `RealmSource` to `WhoamiInfo` |
@@ -412,7 +437,7 @@ auth:
412437
Existing cached credentials will not be found after this update because paths change:
413438

414439
- **Old:** `~/.config/atmos/aws/aws-sso/credentials`
415-
- **New:** `~/.config/atmos/aws/{realm}/aws-sso/credentials`
440+
- **New:** `~/.config/atmos/{realm}/aws/aws-sso/credentials`
416441

417442
### Expected Behavior
418443

@@ -460,9 +485,10 @@ atmos auth login
460485
### Unit Tests
461486

462487
1. Realm computation with env var, config, and auto-hash
463-
2. Sanitization of realm values
464-
3. Path generation with realm
465-
4. Keyring key format with realm
488+
2. Validation of realm values (valid and invalid cases)
489+
3. Error messages for invalid realm values
490+
4. Path generation with realm
491+
5. Keyring key format with realm
466492

467493
### Integration Tests
468494

0 commit comments

Comments
 (0)