@@ -20,27 +20,48 @@ const (
2020 LogstreamCriblEndpoint LogstreamEndpointType = "cribl"
2121 LogstreamDatadogEndpoint LogstreamEndpointType = "datadog"
2222 LogstreamAxiomEndpoint LogstreamEndpointType = "axiom"
23+ LogstreamS3Endpoint LogstreamEndpointType = "s3"
2324)
2425
2526const (
2627 LogTypeConfig LogType = "configuration"
2728 LogTypeNetwork LogType = "network"
2829)
2930
31+ const (
32+ S3AccessKeyAuthentication S3AuthenticationType = "accesskey"
33+ S3RoleARNAuthentication S3AuthenticationType = "rolearn"
34+ )
35+
3036// LogstreamConfiguration type defines a log stream entity in tailscale.
3137type LogstreamConfiguration struct {
32- LogType LogType `json:"logType,omitempty"`
33- DestinationType LogstreamEndpointType `json:"destinationType,omitempty"`
34- URL string `json:"url,omitempty"`
35- User string `json:"user,omitempty"`
38+ LogType LogType `json:"logType,omitempty"`
39+ DestinationType LogstreamEndpointType `json:"destinationType,omitempty"`
40+ URL string `json:"url,omitempty"`
41+ User string `json:"user,omitempty"`
42+ S3Bucket string `json:"s3Bucket,omitempty"`
43+ S3Region string `json:"s3Region,omitempty"`
44+ S3KeyPrefix string `json:"s3KeyPrefix,omitempty"`
45+ S3AuthenticationType S3AuthenticationType `json:"s3AuthenticationType,omitempty"`
46+ S3AccessKeyID string `json:"s3AccessKeyId,omitempty"`
47+ S3RoleARN string `json:"s3RoleArn,omitempty"`
48+ S3ExternalID string `json:"s3ExternalId,omitempty"`
3649}
3750
3851// SetLogstreamConfigurationRequest type defines a request for setting a LogstreamConfiguration.
3952type SetLogstreamConfigurationRequest struct {
40- DestinationType LogstreamEndpointType `json:"destinationType,omitempty"`
41- URL string `json:"url,omitempty"`
42- User string `json:"user,omitempty"`
43- Token string `json:"token,omitempty"`
53+ DestinationType LogstreamEndpointType `json:"destinationType,omitempty"`
54+ URL string `json:"url,omitempty"`
55+ User string `json:"user,omitempty"`
56+ Token string `json:"token,omitempty"`
57+ S3Bucket string `json:"s3Bucket,omitempty"`
58+ S3Region string `json:"s3Region,omitempty"`
59+ S3KeyPrefix string `json:"s3KeyPrefix,omitempty"`
60+ S3AuthenticationType S3AuthenticationType `json:"s3AuthenticationType,omitempty"`
61+ S3AccessKeyID string `json:"s3AccessKeyId,omitempty"`
62+ S3SecretAccessKey string `json:"s3SecretAccessKey,omitempty"`
63+ S3RoleARN string `json:"s3RoleArn,omitempty"`
64+ S3ExternalID string `json:"s3ExternalId,omitempty"`
4465}
4566
4667// LogstreamEndpointType describes the type of the endpoint.
@@ -49,6 +70,9 @@ type LogstreamEndpointType string
4970// LogType describes the type of logging.
5071type LogType string
5172
73+ // S3AuthenticationType describes the type of authentication used to stream logs to a LogstreamS3Endpoint.
74+ type S3AuthenticationType string
75+
5276// LogstreamConfiguration retrieves the tailnet's [LogstreamConfiguration] for the given [LogType].
5377func (lr * LoggingResource ) LogstreamConfiguration (ctx context.Context , logType LogType ) (* LogstreamConfiguration , error ) {
5478 req , err := lr .buildRequest (ctx , http .MethodGet , lr .buildTailnetURL ("logging" , logType , "stream" ))
@@ -78,3 +102,35 @@ func (lr *LoggingResource) DeleteLogstreamConfiguration(ctx context.Context, log
78102
79103 return lr .do (req , nil )
80104}
105+
106+ // AWSExternalID represents an AWS External ID that Tailscale can use to stream logs from a
107+ // particular Tailscale AWS account to a LogstreamS3Endpoint that uses S3RoleARNAuthentication.
108+ type AWSExternalID struct {
109+ ExternalID string `json:"externalId,omitempty"`
110+ TailscaleAWSAccountID string `json:"tailscaleAwsAccountId,omitempty"`
111+ }
112+
113+ // CreateOrGetAwsExternalId gets an AWS External ID that Tailscale can use to stream logs to
114+ // a LogstreamS3Endpoint using S3RoleARNAuthentication, creating a new one for this tailnet
115+ // when necessary.
116+ func (lr * LoggingResource ) CreateOrGetAwsExternalId (ctx context.Context , reusable bool ) (* AWSExternalID , error ) {
117+ req , err := lr .buildRequest (ctx , http .MethodPost , lr .buildTailnetURL ("aws-external-id" ), requestBody (map [string ]bool {
118+ "reusable" : reusable ,
119+ }))
120+ if err != nil {
121+ return nil , err
122+ }
123+ return body [AWSExternalID ](lr , req )
124+ }
125+
126+ // ValidateAWSTrustPolicy validates that Tailscale can assume your AWS IAM role with (and only
127+ // with) the given AWS External ID.
128+ func (lr * LoggingResource ) ValidateAWSTrustPolicy (ctx context.Context , awsExternalID string , roleARN string ) error {
129+ req , err := lr .buildRequest (ctx , http .MethodPost , lr .buildTailnetURL ("aws-external-id" , awsExternalID , "validate-aws-trust-policy" ), requestBody (map [string ]string {
130+ "roleArn" : roleARN ,
131+ }))
132+ if err != nil {
133+ return err
134+ }
135+ return lr .do (req , nil )
136+ }
0 commit comments