Skip to content
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

tailscale: add support for S3 logstreaming #468

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

zehauser
Copy link

@zehauser zehauser commented Jan 22, 2025

We recently added support for S3 logstreaming endpoints to our API. This involved adding several new fields to the LogstreamConfiguration resource (available when the new "s3" destinationType is used), plus a new AWSExternalID resource needed when AWS role-based authentication is used for an S3 logstreaming endpoint.

This commit updates the Terraform provider to reflect these changes. We add support for the new fields to the tailscale_logstream_configuration resource, and create a new tailscale_aws_external_id resource.

Unfortunately, we have to add some special handling for the "user" field of tailscale_logstream_configuration. Previously, we specified a default dummy value of "user" for the "user" field. Now, the PUT LogstreamConfiguration endpoint does not allow any value to be specified for a s3 destinationType. We could loosen that restriction at the API layer, but I would prefer not to do that. However, we don't want to break any existing users who are relying on this default and have it in their Terraform state. So the approach I've chosen is to add special handling for the "user" field:

  • When creating or updating a configuration, if destinationType == "s3" and user == "user", we assume the "user" value came from the default and we do not actually send it to the API.
  • When reading or importing a configuration, if destinationType == "s3" and there is no user field (which should always be true), we set user = "user" in the Terraform state.

Fixes #458
Fixes tailscale/corp#24533

@zehauser zehauser force-pushed the zach/s3-logstreaming branch 2 times, most recently from 9354aac to a0e1650 Compare January 22, 2025 10:26
Copy link
Author

@zehauser zehauser left a comment

Choose a reason for hiding this comment

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

Comment on lines +191 to +192
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20250122081626-c84613baf18d h1:I3Ka+YodSpslWRaHHOtKQiHFcfuTr8o23619oP1P11I=
github.com/tailscale/tailscale-client-go/v2 v2.0.0-20250122081626-c84613baf18d/go.mod h1:i/MSgQ71kdyh1Wdp50XxrIgtsyO4uZ2SZSPd83lGKHM=
Copy link
Author

Choose a reason for hiding this comment

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

We probably need to modify this after tailscale/tailscale-client-go#131 is actually merged.

Comment on lines +179 to +182
if err != nil && tsclient.IsNotFound(err) {
d.SetId("")
return nil
}
Copy link
Author

Choose a reason for hiding this comment

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

Oh right! This is an unrelated bugfix I snuck in. Or at least I think it's a bugfix.

If you delete your Terraform-created logstream configuration out-of-band (e.g. in the admin console), without this fix, we fail with a 404 error on plan. I think probably we should instead detect that the config has been deleted and report that, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'll defer to @mpminardi on this, as I don't know what the usual convention is with Terraform.

@zehauser zehauser self-assigned this Jan 22, 2025
We recently added support for S3 logstreaming endpoints to our API. This
involved adding several new fields to the LogstreamConfiguration resource
(available when the new "s3" destinationType is used), plus a new
AWSExternalID resource needed when AWS role-based authentication is used
for an S3 logstreaming endpoint.

This commit updates the Terraform provider to reflect these changes. We add
support for the new fields to the tailscale_logstream_configuration
resource, and create a new tailscale_aws_external_id resource.

Unfortunately, we have to add some special handling for the "user" field of
tailscale_logstream_configuration. Previously, we specified a default dummy
value of "user" for the "user" field. Now, the PUT LogstreamConfiguration
endpoint does not allow any value to be specified for a s3 destinationType.
We could loosen that restriction at the API layer, but I would prefer not
to do that. However, we don't want to break any existing users who are
relying on this default and have it in their Terraform state. So the
approach I've chosen is to add special handling for the "user" field:
- When creating or updating a configuration, if destinationType == "s3" and
  user == "user", we assume the "user" value came from the default and we
  do not actually send it to the API.
- When reading or importing a configuration, if destinationType == "s3" and
  there is no user field (which should always be true), we set
  user = "user" in the Terraform state.

Fixes #458
Fixes tailscale/corp#24533

Signed-off-by: Zach Hauser <[email protected]>
@zehauser zehauser force-pushed the zach/s3-logstreaming branch from a0e1650 to 21d8c90 Compare January 22, 2025 10:30
func resourceAWSExternalIDCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*tsclient.Client)

aid, err := client.Logging().CreateOrGetAwsExternalId(ctx, tsclient.CreateOrGetAwsExternalIdRequest{Reusable: false})
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be worth a comment on why "reusable" is false, and why it must be.

Copy link
Contributor

@oxtoacart oxtoacart left a comment

Choose a reason for hiding this comment

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

Finished my first round of review.

// corresponding scenario for resourceLogstreamConfigurationRead(), we'll add
// user = 'user' to the state.)
user := d.Get("user").(string)
if destinationType == tsclient.LogstreamS3Endpoint && user == "user" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need the user == "user" check? For S3, we never want to send a user, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

And we if change this, can we get rid of the below?

Comment on lines +179 to +182
if err != nil && tsclient.IsNotFound(err) {
d.SetId("")
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'll defer to @mpminardi on this, as I don't know what the usual convention is with Terraform.

log_type = "network"
destination_type = "s3"
s3_bucket = "example-bucket"
s3_region = "us-west-2"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: weird indentation

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.

Support S3 log streaming
2 participants