// Path: src/main/java/com/google/fleetengine/auth/token/FleetEngineToken.java
// @AutoValue
// public abstract class FleetEngineToken {
//   /** Token creation timestamp. */
//   public abstract Date creationTimestamp();
// 
//   /** Token expiration timestamp. */
//   public abstract Date expirationTimestamp();
// 
//   /** Audience (aud claim) of the JWT. */
//   public abstract String audience();
// 
//   /** Signed and base64 encoded JWT. */
//   @Nullable
//   public abstract String jwt();
// 
//   /** Scope of the authorization token. */
//   public abstract FleetEngineTokenType tokenType();
// 
//   /** Custom authorization claims written to JWT. */
//   public abstract FleetEngineTokenClaims authorizationClaims();
// 
//   /** Provides a builder for {@link FleetEngineToken}. */
//   public static Builder builder() {
//     return new AutoValue_FleetEngineToken.Builder()
//         .setAudience(CommonConstants.DEFAULT_JWT_AUDIENCE);
//   }
// 
//   public abstract FleetEngineToken.Builder toBuilder();
// 
//   /** Builder class for FleetEngineToken. */
//   @AutoValue.Builder
//   public abstract static class Builder {
// 
//     /** Setter for token creation timestamp. */
//     public abstract Builder setCreationTimestamp(Date creationTimestamp);
// 
//     /** Setter for token expiration timestamp. */
//     public abstract Builder setExpirationTimestamp(Date expirationTimestamp);
// 
//     /** Setter for a signed JWT to be associated with the token object. */
//     public abstract Builder setJwt(String token);
// 
//     /** Setter for the token type defining the scope of the token. */
//     public abstract Builder setTokenType(FleetEngineTokenType type);
// 
//     /** Setter for token audience (aud claim). */
//     public abstract Builder setAudience(String audience);
// 
//     /** Sets custom authorization claims written to JWT. */
//     public abstract Builder setAuthorizationClaims(FleetEngineTokenClaims claims);
// 
//     /** Builds the token object. */
//     public abstract FleetEngineToken build();
//   }
// }
// 
// Path: src/main/java/com/google/fleetengine/auth/token/factory/signer/util/CommonConstants.java
// public final class CommonConstants {
//   /* JWT name of the authorization claim.  */
//   public static final String JWT_CLAIM_AUTHORIZATION_PROPERTY = "authorization";
// 
//   /* Default value of the JWT audience (aud claim). */
//   public static final String DEFAULT_JWT_AUDIENCE = "https://fleetengine.googleapis.com/";
// 
//   private CommonConstants() {}
// }


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.fleetengine.auth.token.FleetEngineToken;
import com.google.fleetengine.auth.token.factory.signer.util.CommonConstants;
import java.io.IOException;
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.fleetengine.auth.token.factory.signer;



/**
 * Signs Fleet Engine tokens with the GCP service account that is running the application.
 *
 * <p>The default service account that the application is running under <b>MUST</b> have the
 * iam.serviceAccounts.signBlob permission. This is typically acquired through the "Service Account
 * Token Creator" role.
 *
 * <p>The default service account <b>MUST</b> have the same role as the {@link
 * com.google.fleetengine.auth.token.FleetEngineTokenType} of the token being signed.
 */
public class DefaultServiceAccountSigner implements Signer {
  private static final String ALGORITHM_NAME = "RS256";
  private static final String ALGORITHM_DESCRIPTION = "SHA256withRSA";
  private final ServiceAccountSignerCredentials serviceAccountCredentials;

  /**
   * Creates signer that uses the currently running service account.
   *
   * @throws SignerInitializationException if the credentials cannot be created in the current
   *     environment OR if the default user is not a service account.
   */
  public static DefaultServiceAccountSigner create() throws SignerInitializationException {
    GoogleCredentials defaultCredentials;
    try {
      defaultCredentials = GoogleCredentials.getApplicationDefault();
    } catch (IOException e) {
      throw new SignerInitializationException(
          "Could not retrieve credentials for default application.", e);
    }

    return create(defaultCredentials);
  }

  @VisibleForTesting
  static DefaultServiceAccountSigner create(GoogleCredentials defaultCredentials)
      throws SignerInitializationException {
    if (!(defaultCredentials instanceof ServiceAccountCredentials)) {
      throw new SignerInitializationException(
          "GCP default user account running the application is a NOT a service account.");
    }
    return new DefaultServiceAccountSigner(
        new ServiceAccountSignerCredentials((ServiceAccountCredentials) defaultCredentials));
  }

  /** Constructor. */
  @VisibleForTesting
  DefaultServiceAccountSigner(ServiceAccountSignerCredentials serviceAccountCredentials) {
    this.serviceAccountCredentials = serviceAccountCredentials;
  }

  /**
   * Signs a provided Fleet Engine token with the default service account.
   *
   * <p>The default service account that the application is running under <b>MUST</b> have the
   * iam.serviceAccounts.signBlob permission. This is typically acquired through the "Service
   * Account Token Creator" role.
   *
   * <p>The default service account <b>MUST</b> have the same role as the {@link
   * com.google.fleetengine.auth.token.FleetEngineTokenType} of the token being signed.
   *
   * @param token Fleet Engine token to sign
   * @return same value as the {@code token} parameter except with the JWT property set to a valid
   *     JWT
   */
  @Override
// Path: src/main/java/com/google/fleetengine/auth/token/FleetEngineToken.java
// @AutoValue
// public abstract class FleetEngineToken {
//   /** Token creation timestamp. */
//   public abstract Date creationTimestamp();
// 
//   /** Token expiration timestamp. */
//   public abstract Date expirationTimestamp();
// 
//   /** Audience (aud claim) of the JWT. */
//   public abstract String audience();
// 
//   /** Signed and base64 encoded JWT. */
//   @Nullable
//   public abstract String jwt();
// 
//   /** Scope of the authorization token. */
//   public abstract FleetEngineTokenType tokenType();
// 
//   /** Custom authorization claims written to JWT. */
//   public abstract FleetEngineTokenClaims authorizationClaims();
// 
//   /** Provides a builder for {@link FleetEngineToken}. */
//   public static Builder builder() {
//     return new AutoValue_FleetEngineToken.Builder()
//         .setAudience(CommonConstants.DEFAULT_JWT_AUDIENCE);
//   }
// 
//   public abstract FleetEngineToken.Builder toBuilder();
// 
//   /** Builder class for FleetEngineToken. */
//   @AutoValue.Builder
//   public abstract static class Builder {
// 
//     /** Setter for token creation timestamp. */
//     public abstract Builder setCreationTimestamp(Date creationTimestamp);
// 
//     /** Setter for token expiration timestamp. */
//     public abstract Builder setExpirationTimestamp(Date expirationTimestamp);
// 
//     /** Setter for a signed JWT to be associated with the token object. */
//     public abstract Builder setJwt(String token);
// 
//     /** Setter for the token type defining the scope of the token. */
//     public abstract Builder setTokenType(FleetEngineTokenType type);
// 
//     /** Setter for token audience (aud claim). */
//     public abstract Builder setAudience(String audience);
// 
//     /** Sets custom authorization claims written to JWT. */
//     public abstract Builder setAuthorizationClaims(FleetEngineTokenClaims claims);
// 
//     /** Builds the token object. */
//     public abstract FleetEngineToken build();
//   }
// }
// 
// Path: src/main/java/com/google/fleetengine/auth/token/factory/signer/util/CommonConstants.java
// public final class CommonConstants {
//   /* JWT name of the authorization claim.  */
//   public static final String JWT_CLAIM_AUTHORIZATION_PROPERTY = "authorization";
// 
//   /* Default value of the JWT audience (aud claim). */
//   public static final String DEFAULT_JWT_AUDIENCE = "https://fleetengine.googleapis.com/";
// 
//   private CommonConstants() {}
// }


// Path: src/main/java/com/google/fleetengine/auth/token/factory/signer/DefaultServiceAccountSigner.java
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.fleetengine.auth.token.FleetEngineToken;
import com.google.fleetengine.auth.token.factory.signer.util.CommonConstants;
import java.io.IOException;

// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.fleetengine.auth.token.factory.signer;



/**
 * Signs Fleet Engine tokens with the GCP service account that is running the application.
 *
 * <p>The default service account that the application is running under <b>MUST</b> have the
 * iam.serviceAccounts.signBlob permission. This is typically acquired through the "Service Account
 * Token Creator" role.
 *
 * <p>The default service account <b>MUST</b> have the same role as the {@link
 * com.google.fleetengine.auth.token.FleetEngineTokenType} of the token being signed.
 */
public class DefaultServiceAccountSigner implements Signer {
  private static final String ALGORITHM_NAME = "RS256";
  private static final String ALGORITHM_DESCRIPTION = "SHA256withRSA";
  private final ServiceAccountSignerCredentials serviceAccountCredentials;

  /**
   * Creates signer that uses the currently running service account.
   *
   * @throws SignerInitializationException if the credentials cannot be created in the current
   *     environment OR if the default user is not a service account.
   */
  public static DefaultServiceAccountSigner create() throws SignerInitializationException {
    GoogleCredentials defaultCredentials;
    try {
      defaultCredentials = GoogleCredentials.getApplicationDefault();
    } catch (IOException e) {
      throw new SignerInitializationException(
          "Could not retrieve credentials for default application.", e);
    }

    return create(defaultCredentials);
  }

  @VisibleForTesting
  static DefaultServiceAccountSigner create(GoogleCredentials defaultCredentials)
      throws SignerInitializationException {
    if (!(defaultCredentials instanceof ServiceAccountCredentials)) {
      throw new SignerInitializationException(
          "GCP default user account running the application is a NOT a service account.");
    }
    return new DefaultServiceAccountSigner(
        new ServiceAccountSignerCredentials((ServiceAccountCredentials) defaultCredentials));
  }

  /** Constructor. */
  @VisibleForTesting
  DefaultServiceAccountSigner(ServiceAccountSignerCredentials serviceAccountCredentials) {
    this.serviceAccountCredentials = serviceAccountCredentials;
  }

  /**
   * Signs a provided Fleet Engine token with the default service account.
   *
   * <p>The default service account that the application is running under <b>MUST</b> have the
   * iam.serviceAccounts.signBlob permission. This is typically acquired through the "Service
   * Account Token Creator" role.
   *
   * <p>The default service account <b>MUST</b> have the same role as the {@link
   * com.google.fleetengine.auth.token.FleetEngineTokenType} of the token being signed.
   *
   * @param token Fleet Engine token to sign
   * @return same value as the {@code token} parameter except with the JWT property set to a valid
   *     JWT
   */
  @Override
  public FleetEngineToken sign(FleetEngineToken token) {