func()

in assertion/pkg/tasks/assertion/sign.go [51:144]


func (t *Sign) Run(ctx context.Context) error {
	// Check arguments
	if t.VaultClient == nil {
		return fmt.Errorf("vault client must not be nil")
	}
	if t.TransitKeyName == "" {
		return fmt.Errorf("transit key name is mandatory")
	}
	if t.Subject == "" {
		return fmt.Errorf("subject must not be blank")
	}
	if len(t.Audiences) == 0 {
		return fmt.Errorf("audiences must not be empty")
	}
	if t.Expiration < 1*time.Minute {
		t.Expiration = 1 * time.Minute
	}
	if t.Expiration > 15*time.Minute {
		t.Expiration = 15 * time.Minute
	}

	// Retrieve content reader
	reader, err := t.ContentReader(ctx)
	if err != nil {
		return fmt.Errorf("unable to open content for read: %w", err)
	}

	// Check input as json
	var body map[string]interface{}
	if err = json.NewDecoder(reader).Decode(&body); err != nil {
		return fmt.Errorf("unable to decode input content as JSON: %w", err)
	}

	// Retrieve public key
	pubKey, version, err := jwtvault.GetPublicKey(t.VaultClient, "assertions", t.TransitKeyName)
	if err != nil {
		return fmt.Errorf("unable to retrieve public key: %w", err)
	}

	// Allocate opaque signer
	opaqueSigner := jwtvault.Signer(t.VaultClient, "assertions", t.TransitKeyName, pubKey)

	// Get Public key
	alg := jose.SignatureAlgorithm(opaqueSigner.Public().Algorithm)
	signer, err := jose.NewSigner(
		jose.SigningKey{
			Algorithm: alg,
			Key: &jose.JSONWebKey{
				Algorithm: string(alg),
				Key:       opaqueSigner,
				KeyID:     fmt.Sprintf("vault:assertions:%s:v%d", t.TransitKeyName, version),
				Use:       "sig",
			},
		},
		&jose.SignerOptions{
			EmbedJWK: true,
			ExtraHeaders: map[jose.HeaderKey]interface{}{
				jose.HeaderType: assertionHeaderType,
			},
		},
	)
	if err != nil {
		return fmt.Errorf("unable to allocate token signer: %w", err)
	}

	// Generate token
	now := time.Now()
	assertion, err := jwt.Signed(signer).Claims(body).Claims(&jwt.Claims{
		ID:        uniuri.NewLen(16),
		Expiry:    jwt.NewNumericDate(now.Add(t.Expiration)),
		IssuedAt:  jwt.NewNumericDate(now),
		NotBefore: jwt.NewNumericDate(now.Add(-1 * time.Second)),
		Issuer:    "harp-assertion",
		Subject:   t.Subject,
		Audience:  jwt.Audience(t.Audiences),
	}).CompactSerialize()
	if err != nil {
		return fmt.Errorf("unable to sign final assertion: %w", err)
	}

	// Allocate writer
	writer, err := t.OutputWriter(ctx)
	if err != nil {
		return fmt.Errorf("unable to initialize output writer: %w", err)
	}

	// Dump to writer
	if _, err := fmt.Fprintf(writer, "%s", assertion); err != nil {
		return fmt.Errorf("unable to write assertion to writer: %w", err)
	}

	// No error
	return nil
}