Skip to content

Conversation

guilhermocc
Copy link
Contributor

@guilhermocc guilhermocc commented May 30, 2023

Pull Request check list

  • Commit conforms to CONTRIBUTING.md?
  • Proper tests/regressions included?
  • Documentation updated?

Affected functionality
oidc discovery provider HTTPS configuration.

Description of change
Add new configuration option for oidc discovery provider, so users can now use their own certificates to be used on HTTPS connections. The new configuration structure is described below:

serving_cert_file {
	cert_file_path = "path_to_certificate_file"
	key_file_path = "path_to_private_key_file"
}

Users can now indicate the file path of the certificate and private key that are going to be loaded from the disk and used for establishing TLS connections with clients. Upon start, oidc discovery provider will start watching for file changes in the provided paths and reload the certificate used for connections.

Which issue this PR fixes
Fixes #3825

Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from a92394e to e5e56a9 Compare May 30, 2023 16:41
@guilhermocc guilhermocc marked this pull request as draft May 30, 2023 16:41
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from 47c3661 to f146772 Compare May 31, 2023 17:53
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from f146772 to 09acd52 Compare May 31, 2023 20:19
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from 284e928 to c7f1bdf Compare June 1, 2023 20:34
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from c7f1bdf to 75123b3 Compare June 1, 2023 20:41
@guilhermocc guilhermocc marked this pull request as ready for review June 1, 2023 22:14
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from 5872843 to 92e89f0 Compare June 9, 2023 20:35
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from 92e89f0 to 50eb322 Compare June 9, 2023 21:21
Signed-off-by: Guilherme Carvalho <[email protected]>

tmpDir := t.TempDir()

writeFile(t, tmpDir+keyFilePath, oidcServerKeyPem)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can use filepath.Join here, to avoid using /

certManager, err := NewDiskCertManager(&ServingCertFileConfig{
CertFilePath: tmpDir + certFilePath,
KeyFilePath: tmpDir + keyFilePath,
FileSyncInterval: 10 * time.Millisecond,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead continuos reloading, why not to use a clock mock? and advance time when required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could make the test run faster, but we would still need to use require.Eventually to make some assertions since the time difference between loading a cert and moving the clock + making an assertion can cause errors.

require.NoError(t, err)
}

func assertFileDontExist(t *testing.T, filePath string, err error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may you this to _posix_test || _windows_test and void this if?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that initially, but I didn't like to have two extra files for differentiating only two string constants. Do you think it is worth it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about putting them inside config_XXXX_test? both are on the same package, and you will no need another file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea!

if err != nil {
return nil, err
}
log.Info("Serving HTTPS using certificate loaded from disk")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may we add fields for used files?


tlsConfig := certManager.TLSConfig()

tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{Port: 8080})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this hardcoded port ok?

Copy link
Contributor Author

@guilhermocc guilhermocc Jun 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be 443 for default HTTPS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The acme code for sure used 443. Now that we're not bound to ACME, this could probably be configurable so you don't need CAP_NET_BIND_SERVICE capabilities when testing it out...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, we can provide more flexibility now, I will introduce a new addr configuration in this section.

@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from 8743e34 to c541a57 Compare June 13, 2023 17:49
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from c541a57 to 3d36f1f Compare June 13, 2023 20:04
@@ -56,13 +57,13 @@ The configuration file is **required** by the provider. It contains

#### Considerations for Unix platforms

[1]: One of `acme` or `listen_socket_path` must be defined.
[1]: One of `acme`, `serving_cert_file`, `listen_socket_path` must be defined.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still want the "or" on these lines (same suggestion for the others):

Suggested change
[1]: One of `acme`, `serving_cert_file`, `listen_socket_path` must be defined.
[1]: One of `acme`, `serving_cert_file`, or `listen_socket_path` must be defined.

Comment on lines 103 to 104
err = server.Shutdown(context.Background())
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, it isn't safe to modify the err variable from the goroutine. In practice in this code it is fine because it isn't used after this point. It would be safer to use a new err variable, ideally scoped to the shutdown statement:

if err := server.Shutdown(context.Background()); err != nil {
    log.Error(err)
}

certManager, err := NewDiskCertManager(config.ServingCertFile, log)
if err != nil {
return nil, err
}
go func() {
certManager.WatchFileChanges(ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'll accept this code as-is since it's happening in main, but ideally the lifetime of this goroutine is controlled by the net.Listener it returns, i.e. when the listener is closed, this goroutine shuts down and the listener waits for it to close.


tlsConfig := certManager.TLSConfig()

tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{Port: 8080})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The acme code for sure used 443. Now that we're not bound to ACME, this could probably be configurable so you don't need CAP_NET_BIND_SERVICE capabilities when testing it out...

@guilhermocc
Copy link
Contributor Author

@azdagron thank you very much for the review so far, I've addressed the last comments you made, could you review it again? 😄

Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from b7baa15 to d4e615f Compare June 26, 2023 12:45
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from d4e615f to 996e427 Compare June 26, 2023 13:12
| `key_file_path` | string | required | The private key file path, the file must contain PEM encoded data. | |
| `file_sync_interval` | duration | optional | Controls how frequently the service polls the files for changes. | 1 minute |
| `file_sync_interval` | duration | optional | Controls how frequently the service polls the files for changes. | 1 minute |
| `addr` | string | optional | Exposes the service on the given address. | :433 |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

443 should be the default (multiple places to fix)

Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from 4dde3f1 to dd04ac6 Compare June 30, 2023 18:48
Signed-off-by: Guilherme Carvalho <[email protected]>
@guilhermocc guilhermocc force-pushed the serving-cert-file-oidc-provider branch from dd04ac6 to c18537e Compare June 30, 2023 20:57
@guilhermocc guilhermocc requested a review from azdagron July 3, 2023 16:16
Signed-off-by: Guilherme Carvalho <[email protected]>
@azdagron azdagron added this to the 1.7.1 milestone Jul 3, 2023
Copy link
Member

@azdagron azdagron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @guilhermocc !

@rturner3 rturner3 merged commit d1c58f8 into spiffe:main Jul 4, 2023
Neniel pushed a commit to Neniel/spire that referenced this pull request Jul 10, 2023
* Add disk cert manager

Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Neniel <[email protected]>
Neniel pushed a commit to Neniel/spire that referenced this pull request Jul 21, 2023
* Add disk cert manager

Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Neniel <[email protected]>
Neniel pushed a commit to Neniel/spire that referenced this pull request Aug 24, 2023
* Add disk cert manager

Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Guilherme Carvalho <[email protected]>
Signed-off-by: Neniel <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFE] allow bring your own certs for the oidc-disicovery-provider components
4 participants