aws-rds: oracle password rules not followed + exclude_characters act strange
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
Two problems in the same session ..
1. the [default exclude set](https://github.com/aws/aws-cdk/blob/1fdf1223304e15d905723553a40640b8bcb0ec56/packages/%40aws-cdk/aws-rds/lib/private/util.ts#L13-L21) isn't good enough for oracle
2. "^" can not be the first character in the exclude set.
### Expected Behavior
Specifying the construction of a RDS that happens to have an Oracle engine, should produce a password that is legal for Oracle.
When specifying an exclude string, the sequence of characters should not matter. "^ " is wildly different from " ^" right now.
### Current Behavior
```python
rds.DatabaseInstance(self, "Oracle",
engine=rds.DatabaseInstanceEngine.oracle_ ...
...
credentials=rds.Credentials.from_generated_secret(
username="admin"
),
...)
```
Will start up an Oracle RDS just fine, but the password will probably not work for Oracle, as it will not follow the rules for Oracle passwords:
Your Oracle Password must contain at least 15 characters and include 3 of the following:
- At least one uppercase letter
- At least one lowercase letter
- At least one digit
- At least 1 special character
- only the following special characters are allowed: # $ _
Using the `exclude_characters` specified in https://github.com/aws/aws-cdk/issues/16824#issuecomment-937520774 adjusted slightly to follow the rules, we write this, hoping to get a new database with a better password ..
```python
exclude_characters="^ %+~`$&*()|[]{}:;,-<>?!'/\\\",="
rds.DatabaseInstance(self, "Oracle",
engine=rds.DatabaseInstanceEngine.oracle_ ...
...
credentials=rds.Credentials.from_generated_secret(
username="admin",
exclude_characters=exclude_characters,
),
...)
```
This will result in this error from CloudFormation:
_The parameter MasterUserPassword is not a valid password. Only printable ASCII characters besides '/', '@', '"', ' ' may be used. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterValue;_
Taking the hint, that only printable ASCII characters can be used, and knowing that '/', '@', '"', can't be used in an Oracle password anyway, we can do the following
```python
import string
exclude_characters=string.printable
.replace(string.ascii_letters, "")
.replace(string.digits, "")
.replace(string.whitespace, " ")
.replace('#', "")
.replace("$", "")
.replace("_", "")
# the above evaluates to this:
exclude_characters='!"%&\'()*+,-./:;<=>?@[\\]^`{|}~ '
rds.DatabaseInstance(self, "Oracle",
engine=rds.DatabaseInstanceEngine.oracle_ ...
...
credentials=rds.Credentials.from_generated_secret(
username="admin",
exclude_characters=exclude_characters,
),
...)
```
This works, and produces an Oracle RDS with a password saved as a secret and a password that is allowed by Oracle.
At this point, I looked at the failing and the working sequences of exclude_characters:
```
exclude_characters='!"%&\'()*+,-./:;<=>?@[\\]^`{|}~ '
exclude_characters="^ %+~`&*()|[]{}:;,-<>?!'/\\\",="
```
These contain exactly the same characters, but the sequences are different
The minimal change it's possible to make to the last of the two strings above is this:
```
exclude_characters=" ^%+~`&*()|[]{}:;,-<>?!'/\\\",="
```
So if `exclude_characters` start with a `^`, CloudFormation errors as described above. If the `^` is moved a bit, everything works perfectly.
### Reproduction Steps
Make an Oracle RDS like this:
```python
rds.DatabaseInstance(self, "Oracle",
engine=rds.DatabaseInstanceEngine.oracle_ ...
...
credentials=rds.Credentials.from_generated_secret(
username="admin"
),
...)
```
Ignore the database, check the actual password in the secret store, and notice that it does not conform to the password rules set by Oracle. Try to log into the database with the password in the secret store and observe that you get an error.
SECOND
Make an Oracle RDS like this:
```python
exclude_characters="^ %+~`&*()|[]{}:;,-<>?!'/\\\",="
rds.DatabaseInstance(self, "Oracle",
engine=rds.DatabaseInstanceEngine.oracle_ ...
...
credentials=rds.Credentials.from_generated_secret(
username="admin",
exclude_characters=exclude_characters,
),
...)
```
Observe that CloudFormation chokes out with the error:
change `exclude_characters` to
```
exclude_characters=" ^%+~`&*()|[]{}:;,-<>?!'/\\\",="
```
observe that CloudFormation accepts the stack, creates the database and that the password in secret store conform to the rules set by Oracle. Check that you can log into the database.
To prove, that the leading `^` is a problem, just use `rds.Credentials.from_generated_secret` with any db engine, exclude some characters and lead with the `^`. CloudFormation will choke.
### Possible Solution
Solution for the first problem:
Just adjust
```
export const DEFAULT_PASSWORD_EXCLUDE_CHARS = " %+~`#$&*()|[]{}:;<>?!'/@\"\\";
```
to
```
export const DEFAULT_PASSWORD_EXCLUDE_CHARS = " %+~`&*()|[]{}:;<>?!'/@\"\\";
```
here:
https://github.com/aws/aws-cdk/blob/1fdf1223304e15d905723553a40640b8bcb0ec56/packages/%40aws-cdk/aws-rds/lib/private/util.ts#L13-L21
The solution to the second problem is a bit more tricky and I have no idea about a possible fix. Somewhere in the path of the use of `exclude_character`, that parameter is used as a regexp character class. ^ has a special meaning in such situations and may explain why the string with a leading ^ messes thing up.
### Additional Information/Context
This issue started as a helping reminder on this issue: https://github.com/aws/aws-cdk/issues/16824
### CDK CLI Version
2.17.0 (build f9cd009)
### Framework Version
aws-cdk-lib 2.16.0
### Node.js Version
v17.7.1
### OS
macOS Monterey, Version 12.2.1
### Language
Python
### Language Version
3.9.10
### Other information
_No response_
Contributor guide
Research direction
Start in packages/@aws-cdk/aws-rds/lib/private/util.ts at DEFAULT_PASSWORD_EXCLUDE_CHARS, then trace Credentials.from_generated_secret and the exclude_characters path. Reproduce both Oracle password-rule and leading-^ cases; done means the default excludes Oracle-invalid characters and any ordering of excluded characters is accepted by CloudFormation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100