go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/machinetoken/bigquery_log.go (about)

     1  // Copyright 2017 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package machinetoken
    16  
    17  import (
    18  	"context"
    19  	"math/big"
    20  	"net"
    21  
    22  	"google.golang.org/protobuf/types/known/timestamppb"
    23  
    24  	tokenserver "go.chromium.org/luci/tokenserver/api"
    25  	bqpb "go.chromium.org/luci/tokenserver/api/bq"
    26  	"go.chromium.org/luci/tokenserver/api/minter/v1"
    27  
    28  	"go.chromium.org/luci/tokenserver/appengine/impl/certconfig"
    29  	"go.chromium.org/luci/tokenserver/appengine/impl/utils"
    30  	"go.chromium.org/luci/tokenserver/appengine/impl/utils/bq"
    31  )
    32  
    33  func init() {
    34  	bq.RegisterTokenKind("machine_tokens", (*bqpb.MachineToken)(nil))
    35  }
    36  
    37  // MintedTokenInfo is passed to LogToken.
    38  //
    39  // It carries all information about the token minting operation and the produced
    40  // token.
    41  type MintedTokenInfo struct {
    42  	Request   *minter.MachineTokenRequest   // the token request, as presented by the client
    43  	Response  *minter.MachineTokenResponse  // the response, as returned by the minter
    44  	TokenBody *tokenserver.MachineTokenBody // deserialized token (same as in Response)
    45  	CA        *certconfig.CA                // CA configuration used to authorize this request
    46  	PeerIP    net.IP                        // caller IP address
    47  	RequestID string                        // GAE request ID that handled the RPC
    48  }
    49  
    50  // toBigQueryMessage returns a message to upload to BigQuery.
    51  func (i *MintedTokenInfo) toBigQueryMessage() *bqpb.MachineToken {
    52  	// LUCI_MACHINE_TOKEN is the only supported type currently.
    53  	if i.Request.TokenType != tokenserver.MachineTokenType_LUCI_MACHINE_TOKEN {
    54  		panic("unknown token type")
    55  	}
    56  	return &bqpb.MachineToken{
    57  		// Identifier of the token body.
    58  		Fingerprint: utils.TokenFingerprint(i.Response.GetLuciMachineToken().MachineToken),
    59  
    60  		// Information about the token.
    61  		MachineFqdn:        i.TokenBody.MachineFqdn,
    62  		TokenType:          i.Request.TokenType,
    63  		IssuedAt:           &timestamppb.Timestamp{Seconds: int64(i.TokenBody.IssuedAt)},
    64  		Expiration:         &timestamppb.Timestamp{Seconds: int64(i.TokenBody.IssuedAt + i.TokenBody.Lifetime)},
    65  		CertSerialNumber:   new(big.Int).SetBytes(i.TokenBody.CertSn).String(),
    66  		SignatureAlgorithm: i.Request.SignatureAlgorithm,
    67  
    68  		// Information about the CA used to authorize this request.
    69  		CaCommonName: i.CA.CN,
    70  		CaConfigRev:  i.CA.UpdatedRev,
    71  
    72  		// Information about the request handler.
    73  		PeerIp:         i.PeerIP.String(),
    74  		ServiceVersion: i.Response.ServiceVersion,
    75  		GaeRequestId:   i.RequestID,
    76  	}
    77  }
    78  
    79  // TokenLogger records info about the token to BigQuery.
    80  type TokenLogger func(context.Context, *MintedTokenInfo) error
    81  
    82  // NewTokenLogger returns a callback that records info about tokens to BigQuery.
    83  //
    84  // Tokens themselves are not logged. Only first 16 bytes of their SHA256 hashes
    85  // (aka 'fingerprint') are. They are used only to identify tokens in logs.
    86  //
    87  // When dryRun is true, logs to the local text log only, not to BigQuery
    88  // (to avoid accidentally pushing fake data to real BigQuery dataset).
    89  func NewTokenLogger(dryRun bool) TokenLogger {
    90  	return func(ctx context.Context, i *MintedTokenInfo) error {
    91  		return bq.LogToken(ctx, i.toBigQueryMessage(), dryRun)
    92  	}
    93  }