-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add custom tls config support to mysql #184
feat: add custom tls config support to mysql #184
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(left a few comments in-line here to explain some of the decisions)
"${UP}" alpha xpkg xp-extract --from-xpkg "${OUTPUT_DIR}"/xpkg/linux_"${SAFEHOSTARCH}"/"${PACKAGE_NAME}"-"${VERSION}".xpkg -o "${CACHE_PATH}/${PACKAGE_NAME}.gz" | ||
chmod 644 "${CACHE_PATH}/${PACKAGE_NAME}.gz" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was broken down onto two lines instead of &&
because that silenced all errors in up alpha xpkg
command and continued with rest of script in case of failures.
echo_step "installing MariaDB Helm chart into default namespace" | ||
mariadb_root_pw=$(LC_ALL=C tr -cd "A-Za-z0-9" </dev/urandom | head -c 32) | ||
# install MariaDB chart | ||
mariadb_root_pw=$(openssl rand -base64 32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably a better way to generate a random password, because the previous approach was generating errors:
tr: write error: Broken pipe
tr: write error
because head
had to truncate its input stream and close its pipe, which tr
complained about. It was still working OK, even with the error message, probably because set -o pipefail
is not set.
@@ -265,10 +266,10 @@ echo "${INSTALL_YAML}" | "${KUBECTL}" delete -f - | |||
timeout=60 | |||
current=0 | |||
step=3 | |||
while [[ $(kubectl get providerrevision.pkg.crossplane.io -o name | wc -l) != "0" ]]; do | |||
while [[ $(kubectl get providerrevision.pkg.crossplane.io -o name | wc -l | tr -d '[:space:]') != "0" ]]; do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On macOS, the wc -l
command is outputting the count with leading/trailing whitespace, which made that check wait infinitely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably also depending on PATH and brew packages, because I didn't notice anything on my mac :) But since this works on linux and in CI here I totally approve on the change 👍
current=$((current + step)) | ||
if [[ $current -ge $timeout ]]; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was also not ever timing out (only on macOS?), because doing integer operations/comparisons requires this special syntax.
init.sql: | | ||
CREATE USER 'test'@'%' IDENTIFIED BY '${mariadb_test_pw}' REQUIRE X509; | ||
GRANT ALL PRIVILEGES ON *.* TO 'test'@'%' WITH GRANT OPTION; | ||
FLUSH PRIVILEGES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A dedicated test
user is required in order to specifically require X509 on it, but not for admin
user, which is also used for health probes without TLS.
auth: | ||
rootPassword: ${mariadb_root_pw} | ||
primary: | ||
extraFlags: "--ssl --require-secure-transport=ON --ssl-ca=/opt/bitnami/mariadb/certs/ca-cert.pem --ssl-cert=/opt/bitnami/mariadb/certs/server-cert.pem --ssl-key=/opt/bitnami/mariadb/certs/server-key.pem" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that --require-secure-transport=ON
is not sufficient to require client to also provide its cert, we must also turn on REQUIRE X509
on specific users (see below).
namespace: default | ||
name: mariadb-creds | ||
key: client-key.pem | ||
insecureSkipVerify: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
insecureSkipVerify
is to be used only here in e2e tests, because certs are self-signed, otherwise server would reject its own cert.
) | ||
|
||
const ( | ||
errTrackPCUsage = "cannot track ProviderConfig usage" | ||
errGetPC = "cannot get ProviderConfig" | ||
errNoSecretRef = "ProviderConfig does not reference a credentials Secret" | ||
errGetSecret = "cannot get credentials Secret" | ||
errTLSConfig = "cannot load TLS config" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used an error constant for consistency here, even though Crossplane contribution guidelines no longer recommend using them.
@Duologic @chlunde @iainlane sorry for pinging you directly, I saw you seem to have been active here recently. Would just appreciate your cue on whether you think such a PR is likely to be reviewed on the short term, or if we should rather assume that we'll need to build and use our own fork for the next few months? Thanks! 🙏 |
// +optional | ||
TLS *string `json:"tls"` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you may consider enforcing this
https://kubernetes.io/docs/reference/using-api/cel/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be an interesting exercise, but I have never used CEL, would need to read up on it and learn it, so I'd maybe hope to get away with it! 😅
pkg/controller/mysql/tls/tls.go
Outdated
return err | ||
} | ||
|
||
return mysql.RegisterTLSConfig("custom", &tls.Config{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like "custom" is a global key here. I think this must have a unique name per DB if you connect to two databases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! 👍 I have now fixed it by making the key suffixed with provider config name, in order to support multiple configs.
@@ -115,6 +117,10 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E | |||
return nil, errors.Wrap(err, errGetSecret) | |||
} | |||
|
|||
if err := tls.LoadConfig(ctx, c.kube, pc.Spec.TLS, pc.Spec.TLSConfig); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: can and should this be called in newDB instead? It's something you always have to call before newDB? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could merge the two, but I see newDB
as a non-failing function with no external calls, no error result, etc, and I also perceive those two functions as conceptually different. We would need to refactor newDB
considerably, along with corresponding unit tests, as it would slightly affect its scope/role. I tried to be as little intrusive as possible with my changes, but if we commonly decide that they should be merged together, I will tackle that refactoring.
@silphid not sure if we should duplicate the full integration test, because there's also talk about adding PG integration tests. Two ideas:
@Duologic @Bastichou what do you think? |
b497c14
to
bdd825a
Compare
5ec439d
to
4d12693
Compare
All right, I went ahead and refactored all integration tests into more modular shell functions. I kept them inline for now, as we only have mysql tests, but eventually if we add tests for PG, they would be easy to extract into other files that could be sourced. I'm pretty satisfied with the result, which is IMO much cleaner and readable. Let me know what you think! :) |
Signed-off-by: Mathieu Frenette <[email protected]>
Signed-off-by: Mathieu Frenette <[email protected]>
Signed-off-by: Mathieu Frenette <[email protected]>
4d12693
to
6d9c446
Compare
@chlunde I appreciate everyone is busy with their own projects, with little spare time left, but if it was possible to get a quick review on this one, I would be extremely grateful! 🙏☀️ We're hoping to start using those changes via the official release channel, but otherwise the plan is to setup the CI/CD for our fork internally, which I would sincerely prefer to avoid, if possible! 😅 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, as far as I can see this looks good. I'm not a MySQL user so I can't fully vet this (and not a maintainer of provider-sql).
FYI @Duologic
@silphid when merged to main, there will be a image built even if there is no release, so it is possible to install it in a cluster without duplicating the pipeline.
4886268
to
6d9c446
Compare
Description of your changes
This PR adds support for custom TLS configuration to mysql implementation. In provider config file, if
tls
is set tocustom
, it reads custom TLS configuration fromtlsConfig
property, reading CA cert and client key/pair from K8s secret(s), and registering that config in mysql driver under thecustom
key.Even though the mysql driver allows for multiple tls config key/value pairs, in the context of the provider it didn't appear to make sense to allow user to configure multiple TLS configurations and select only one of them, therefore the
tlsConfig
property is not a map, but rather a single config entry.I have:
make reviewable
to ensure this PR is ready for review.How has this code been tested
Because e2e tests require a totally different setup with a TLS-enabled mariaDB instance (but with same test cases), the current test script was duplicated and modified to add TLS, making sure that
make test-integration
runs both the no-tls and tls test scripts. It would be possible to refactor both scripts to combine them together and reduce duplication of setup and test code, however to the cost of readability. Let me know if that is a blocker and I will address it, I just didn't want to introduce more complexity in e2e test script until you confirm that's really what you prefer.