You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: path_roles.go
    path of file: ./repos/vault/builtin/logical/ssh
    
    the code of the file until where you have to start completion: // Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package ssh

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/hashicorp/go-secure-stdlib/parseutil"
	"github.com/hashicorp/vault/sdk/framework"
	"github.com/hashicorp/vault/sdk/helper/cidrutil"
	"github.com/hashicorp/vault/sdk/helper/consts"
	"github.com/hashicorp/vault/sdk/logical"
	"golang.org/x/crypto/ssh"
)

const (
	// KeyTypeOTP is an key of type OTP
	KeyTypeOTP = "otp"
	// KeyTypeDynamic is dynamic key type; removed.
	KeyTypeDynamic = "dynamic"
	// KeyTypeCA is an key of type CA
	KeyTypeCA = "ca"

	// DefaultAlgorithmSigner is the default RSA signing algorithm
	DefaultAlgorithmSigner = "default"

	// Present version of the sshRole struct; when adding a new field or are
	// needing to perform a migration, increment this struct and read the note
	// in checkUpgrade(...).
	roleEntryVersion = 3
)

// Structure that represents a role in SSH backend. This is a common role structure
// for both OTP and CA roles. Not all the fields are mandatory for both type.
// Some are applicable for one and not for other. It doesn't matter.
type sshRole struct {
	KeyType                    string            `mapstructure:"key_type" json:"key_type"`
	DefaultUser                string            `mapstructure:"default_user" json:"default_user"`
	DefaultUserTemplate        bool              `mapstructure:"default_user_template" json:"default_user_template"`
	CIDRList                   string            `mapstructure:"cidr_list" json:"cidr_list"`

    
func (b *backend) pathRoleWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	roleName := d.Get("role").(string)
	if roleName == "" {
		return logical.ErrorResponse("missing role name"), nil
	}

	// Allowed users is an optional field, applicable for both OTP and CA types.
	allowedUsers := d.Get("allowed_users").(string)

	// Validate the CIDR blocks
	cidrList := d.Get("cidr_list").(string)
	if cidrList != "" {
		valid, err := cidrutil.ValidateCIDRListString(cidrList, ",")
		if err != nil {
			return nil, fmt.Errorf("failed to validate cidr_list: %w", err)
		}
		if !valid {
			return logical.ErrorResponse("failed to validate cidr_list"), nil
		}
	}

	// Validate the excluded CIDR blocks
	excludeCidrList := d.Get("exclude_cidr_list").(string)
	if excludeCidrList != "" {
		valid, err := cidrutil.ValidateCIDRListString(excludeCidrList, ",")
		if err != nil {
			return nil, fmt.Errorf("failed to validate exclude_cidr_list entry: %w", err)
		}
		if !valid {
			return logical.ErrorResponse(fmt.Sprintf("failed to validate exclude_cidr_list entry: %v", err)), nil
		}
	}

	port := d.Get("port").(int)
	if port == 0 {
		port = 22
	}

	keyType := d.Get("key_type").(string)
	if keyType == "" {
		return logical.ErrorResponse("missing key type"), nil
	}
	keyType = strings.ToLower(keyType)

	var roleEntry sshRole
	if keyType == KeyTypeOTP {
		defaultUser := d.Get("default_user").(string)
		if defaultUser == "" {
			return logical.ErrorResponse("missing default user"), nil
		}

		// Below are the only fields used from the role structure for OTP type.
		roleEntry = sshRole{
			DefaultUser:     defaultUser,
			CIDRList:        cidrList,
			ExcludeCIDRList: excludeCidrList,
			KeyType:         KeyTypeOTP,
			Port:            port,
			AllowedUsers:    allowedUsers,
			Version:         roleEntryVersion,
		}
	} else if keyType == KeyTypeDynamic {
		return logical.ErrorResponse("dynamic key type roles are no longer supported"), nil
	} else if keyType == KeyTypeCA {
		algorithmSigner := DefaultAlgorithmSigner
		algorithmSignerRaw, ok := d.GetOk("algorithm_signer")
		if ok {
			algorithmSigner = algorithmSignerRaw.(string)
			switch algorithmSigner {
			case ssh.SigAlgoRSA, ssh.SigAlgoRSASHA2256, ssh.SigAlgoRSASHA2512:
			case "", DefaultAlgorithmSigner:
				// This case is valid, and the sign operation will use the signer's
				// default algorithm. Explicitly reset the value to the default value
				// rather than use the more vague implicit empty string.
				algorithmSigner = DefaultAlgorithmSigner
			default:
				return nil, fmt.Errorf("unknown algorithm signer %q", algorithmSigner)
			}
		}

		role, errorResponse := b.createCARole(allowedUsers, d.Get("default_user").(string), algorithmSigner, d)
		if errorResponse != nil {
			return errorResponse, nil
		}
		roleEntry = *role
	} else {
		return logical.ErrorResponse("invalid key type"), nil
	}

	entry, err := logical.StorageEntryJSON(fmt.Sprintf("roles/%s", roleName), roleEntry)
	if err != nil {
		return nil, err
	}

	if err := req.Storage.Put(ctx, entry); err != nil {
		return nil, err
	}
	return nil, nil
}