github.com/vmware/govmomi@v0.51.0/sts/internal/types.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package internal
     6  
     7  // The sts/internal package provides the types for invoking the sts.Issue method.
     8  // The sts.Issue and SessionManager LoginByToken methods require an XML signature.
     9  // Unlike the JRE and .NET runtimes, the Go stdlib does not support XML signing.
    10  // We should considering contributing to the goxmldsig package and gosaml2 to meet
    11  // the needs of sts.Issue rather than maintaining this package long term.
    12  // The tricky part of xmldig is the XML canonicalization (C14N), which is responsible
    13  // for most of the make-your-eyes bleed XML formatting in this package.
    14  // C14N is also why some structures use xml.Name without a field tag and methods modify the xml.Name directly,
    15  // though also working around Go's handling of XML namespace prefixes.
    16  // Most of the types in this package were originally generated from the wsdl and hacked up gen/ scripts,
    17  // but have since been modified by hand.
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"crypto/sha256"
    23  	"encoding/base64"
    24  	"fmt"
    25  	"log"
    26  	"path"
    27  	"reflect"
    28  	"strings"
    29  
    30  	"github.com/vmware/govmomi/vim25/soap"
    31  	"github.com/vmware/govmomi/vim25/types"
    32  	"github.com/vmware/govmomi/vim25/xml"
    33  )
    34  
    35  const (
    36  	XSI    = "http://www.w3.org/2001/XMLSchema-instance"
    37  	WSU    = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    38  	DSIG   = "http://www.w3.org/2000/09/xmldsig#"
    39  	SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
    40  	Time   = "2006-01-02T15:04:05.000Z"
    41  )
    42  
    43  // Security is used as soap.Envelope.Header.Security when signing requests.
    44  type Security struct {
    45  	XMLName             xml.Name `xml:"wsse:Security"`
    46  	WSSE                string   `xml:"xmlns:wsse,attr"`
    47  	WSU                 string   `xml:"xmlns:wsu,attr"`
    48  	Timestamp           Timestamp
    49  	BinarySecurityToken *BinarySecurityToken `xml:",omitempty"`
    50  	UsernameToken       *UsernameToken       `xml:",omitempty"`
    51  	Assertion           string               `xml:",innerxml"`
    52  	Signature           *Signature           `xml:",omitempty"`
    53  }
    54  
    55  type Timestamp struct {
    56  	XMLName xml.Name `xml:"wsu:Timestamp"`
    57  	NS      string   `xml:"xmlns:wsu,attr"`
    58  	ID      string   `xml:"wsu:Id,attr"`
    59  	Created string   `xml:"wsu:Created"`
    60  	Expires string   `xml:"wsu:Expires"`
    61  }
    62  
    63  func (t *Timestamp) C14N() string {
    64  	return Marshal(t)
    65  }
    66  
    67  type BinarySecurityToken struct {
    68  	XMLName      xml.Name `xml:"wsse:BinarySecurityToken"`
    69  	EncodingType string   `xml:"EncodingType,attr"`
    70  	ValueType    string   `xml:"ValueType,attr"`
    71  	ID           string   `xml:"wsu:Id,attr"`
    72  	Value        string   `xml:",chardata"`
    73  }
    74  
    75  type UsernameToken struct {
    76  	XMLName  xml.Name `xml:"wsse:UsernameToken"`
    77  	Username string   `xml:"wsse:Username"`
    78  	Password string   `xml:"wsse:Password"`
    79  }
    80  
    81  type Signature struct {
    82  	XMLName        xml.Name
    83  	NS             string `xml:"xmlns:ds,attr"`
    84  	ID             string `xml:"Id,attr"`
    85  	SignedInfo     SignedInfo
    86  	SignatureValue Value
    87  	KeyInfo        KeyInfo
    88  }
    89  
    90  func (s *Signature) C14N() string {
    91  	return fmt.Sprintf(`<ds:Signature xmlns:ds="%s">%s%s%s</ds:Signature>`,
    92  		DSIG, s.SignedInfo.C14N(), s.SignatureValue.C14N(), s.KeyInfo.C14N())
    93  }
    94  
    95  type SignedInfo struct {
    96  	XMLName                xml.Name
    97  	NS                     string `xml:"xmlns:ds,attr,omitempty"`
    98  	CanonicalizationMethod Method
    99  	SignatureMethod        Method
   100  	Reference              []Reference
   101  }
   102  
   103  func (s SignedInfo) C14N() string {
   104  	ns := "" // empty in ActAs c14n form for example
   105  	if s.NS != "" {
   106  		ns = fmt.Sprintf(` xmlns:ds="%s"`, s.NS)
   107  	}
   108  
   109  	c14n := []string{fmt.Sprintf("<ds:SignedInfo%s>", ns)}
   110  	c14n = append(c14n, s.CanonicalizationMethod.C14N(), s.SignatureMethod.C14N())
   111  	for i := range s.Reference {
   112  		c14n = append(c14n, s.Reference[i].C14N())
   113  	}
   114  	c14n = append(c14n, "</ds:SignedInfo>")
   115  
   116  	return strings.Join(c14n, "")
   117  }
   118  
   119  type Method struct {
   120  	XMLName   xml.Name
   121  	Algorithm string `xml:",attr"`
   122  }
   123  
   124  func (m *Method) C14N() string {
   125  	return mkns("ds", m, &m.XMLName)
   126  }
   127  
   128  type Value struct {
   129  	XMLName xml.Name
   130  	Value   string `xml:",innerxml"`
   131  }
   132  
   133  func (v *Value) C14N() string {
   134  	return mkns("ds", v, &v.XMLName)
   135  }
   136  
   137  type Reference struct {
   138  	XMLName      xml.Name
   139  	URI          string `xml:",attr"`
   140  	Transforms   Transforms
   141  	DigestMethod Method
   142  	DigestValue  Value
   143  }
   144  
   145  func (r Reference) C14N() string {
   146  	for i := range r.Transforms.Transform {
   147  		t := &r.Transforms.Transform[i]
   148  		t.XMLName.Local = "ds:Transform"
   149  		t.XMLName.Space = ""
   150  
   151  		if t.InclusiveNamespaces != nil {
   152  			name := &t.InclusiveNamespaces.XMLName
   153  			if !strings.HasPrefix(name.Local, "ec:") {
   154  				name.Local = "ec:" + name.Local
   155  				name.Space = ""
   156  			}
   157  			t.InclusiveNamespaces.NS = t.Algorithm
   158  		}
   159  	}
   160  
   161  	c14n := []string{
   162  		fmt.Sprintf(`<ds:Reference URI="%s">`, r.URI),
   163  		r.Transforms.C14N(),
   164  		r.DigestMethod.C14N(),
   165  		r.DigestValue.C14N(),
   166  		"</ds:Reference>",
   167  	}
   168  
   169  	return strings.Join(c14n, "")
   170  }
   171  
   172  func NewReference(id string, val string) Reference {
   173  	sum := sha256.Sum256([]byte(val))
   174  
   175  	return Reference{
   176  		XMLName: xml.Name{Local: "ds:Reference"},
   177  		URI:     "#" + id,
   178  		Transforms: Transforms{
   179  			XMLName: xml.Name{Local: "ds:Transforms"},
   180  			Transform: []Transform{
   181  				Transform{
   182  					XMLName:   xml.Name{Local: "ds:Transform"},
   183  					Algorithm: "http://www.w3.org/2001/10/xml-exc-c14n#",
   184  				},
   185  			},
   186  		},
   187  		DigestMethod: Method{
   188  			XMLName:   xml.Name{Local: "ds:DigestMethod"},
   189  			Algorithm: "http://www.w3.org/2001/04/xmlenc#sha256",
   190  		},
   191  		DigestValue: Value{
   192  			XMLName: xml.Name{Local: "ds:DigestValue"},
   193  			Value:   base64.StdEncoding.EncodeToString(sum[:]),
   194  		},
   195  	}
   196  }
   197  
   198  type Transforms struct {
   199  	XMLName   xml.Name
   200  	Transform []Transform
   201  }
   202  
   203  func (t *Transforms) C14N() string {
   204  	return mkns("ds", t, &t.XMLName)
   205  }
   206  
   207  type Transform struct {
   208  	XMLName             xml.Name
   209  	Algorithm           string               `xml:",attr"`
   210  	InclusiveNamespaces *InclusiveNamespaces `xml:",omitempty"`
   211  }
   212  
   213  type InclusiveNamespaces struct {
   214  	XMLName    xml.Name
   215  	NS         string `xml:"xmlns:ec,attr,omitempty"`
   216  	PrefixList string `xml:",attr"`
   217  }
   218  
   219  type X509Data struct {
   220  	XMLName         xml.Name
   221  	X509Certificate string `xml:",innerxml"`
   222  }
   223  
   224  type KeyInfo struct {
   225  	XMLName                xml.Name
   226  	NS                     string                  `xml:"xmlns:ds,attr,omitempty"`
   227  	SecurityTokenReference *SecurityTokenReference `xml:",omitempty"`
   228  	X509Data               *X509Data               `xml:",omitempty"`
   229  }
   230  
   231  func (o *KeyInfo) C14N() string {
   232  	names := []*xml.Name{
   233  		&o.XMLName,
   234  	}
   235  
   236  	if o.SecurityTokenReference != nil {
   237  		names = append(names, &o.SecurityTokenReference.XMLName)
   238  	}
   239  	if o.X509Data != nil {
   240  		names = append(names, &o.X509Data.XMLName)
   241  	}
   242  
   243  	return mkns("ds", o, names...)
   244  }
   245  
   246  type SecurityTokenReference struct {
   247  	XMLName       xml.Name           `xml:"wsse:SecurityTokenReference"`
   248  	WSSE11        string             `xml:"xmlns:wsse11,attr,omitempty"`
   249  	TokenType     string             `xml:"wsse11:TokenType,attr,omitempty"`
   250  	Reference     *SecurityReference `xml:",omitempty"`
   251  	KeyIdentifier *KeyIdentifier     `xml:",omitempty"`
   252  }
   253  
   254  type SecurityReference struct {
   255  	XMLName   xml.Name `xml:"wsse:Reference"`
   256  	URI       string   `xml:",attr"`
   257  	ValueType string   `xml:",attr"`
   258  }
   259  
   260  type KeyIdentifier struct {
   261  	XMLName   xml.Name `xml:"wsse:KeyIdentifier"`
   262  	ID        string   `xml:",innerxml"`
   263  	ValueType string   `xml:",attr"`
   264  }
   265  
   266  type Issuer struct {
   267  	XMLName xml.Name
   268  	Format  string `xml:",attr"`
   269  	Value   string `xml:",innerxml"`
   270  }
   271  
   272  func (i *Issuer) C14N() string {
   273  	return mkns("saml2", i, &i.XMLName)
   274  }
   275  
   276  type Assertion struct {
   277  	XMLName            xml.Name
   278  	ID                 string `xml:",attr"`
   279  	IssueInstant       string `xml:",attr"`
   280  	Version            string `xml:",attr"`
   281  	Issuer             Issuer
   282  	Signature          Signature
   283  	Subject            Subject
   284  	Conditions         Conditions
   285  	AuthnStatement     AuthnStatement
   286  	AttributeStatement AttributeStatement
   287  }
   288  
   289  func (a *Assertion) C14N() string {
   290  	start := `<saml2:Assertion xmlns:saml2="%s" ID="%s" IssueInstant="%s" Version="%s">`
   291  	c14n := []string{
   292  		fmt.Sprintf(start, a.XMLName.Space, a.ID, a.IssueInstant, a.Version),
   293  		a.Issuer.C14N(),
   294  		a.Signature.C14N(),
   295  		a.Subject.C14N(),
   296  		a.Conditions.C14N(),
   297  		a.AuthnStatement.C14N(),
   298  		a.AttributeStatement.C14N(),
   299  		`</saml2:Assertion>`,
   300  	}
   301  
   302  	return strings.Join(c14n, "")
   303  }
   304  
   305  type NameID struct {
   306  	XMLName xml.Name
   307  	Format  string `xml:",attr"`
   308  	ID      string `xml:",innerxml"`
   309  }
   310  
   311  type Subject struct {
   312  	XMLName             xml.Name
   313  	NameID              NameID
   314  	SubjectConfirmation SubjectConfirmation
   315  }
   316  
   317  func (s *Subject) C14N() string {
   318  	data := &s.SubjectConfirmation.SubjectConfirmationData
   319  	names := []*xml.Name{
   320  		&s.XMLName,
   321  		&s.NameID.XMLName,
   322  		&s.SubjectConfirmation.XMLName,
   323  		&data.XMLName,
   324  	}
   325  	if s.SubjectConfirmation.NameID != nil {
   326  		names = append(names, &s.SubjectConfirmation.NameID.XMLName)
   327  	}
   328  	if data.KeyInfo != nil {
   329  		data.NS = XSI
   330  		data.Type = "saml2:KeyInfoConfirmationDataType"
   331  		data.KeyInfo.XMLName = xml.Name{Local: "ds:KeyInfo"}
   332  		data.KeyInfo.X509Data.XMLName = xml.Name{Local: "ds:X509Data"}
   333  		data.KeyInfo.NS = DSIG
   334  	}
   335  	return mkns("saml2", s, names...)
   336  }
   337  
   338  type SubjectConfirmationData struct {
   339  	XMLName      xml.Name
   340  	NS           string `xml:"xmlns:xsi,attr,omitempty"`
   341  	Type         string `xml:"xsi:type,attr,omitempty"`
   342  	NotOnOrAfter string `xml:",attr,omitempty"`
   343  	KeyInfo      *KeyInfo
   344  }
   345  
   346  type SubjectConfirmation struct {
   347  	XMLName                 xml.Name
   348  	Method                  string `xml:",attr"`
   349  	NameID                  *NameID
   350  	SubjectConfirmationData SubjectConfirmationData
   351  }
   352  
   353  type Condition struct {
   354  	Type string `xml:"xsi:type,attr,omitempty"`
   355  }
   356  
   357  func (c *Condition) GetCondition() *Condition {
   358  	return c
   359  }
   360  
   361  type BaseCondition interface {
   362  	GetCondition() *Condition
   363  }
   364  
   365  func init() {
   366  	types.Add("BaseCondition", reflect.TypeOf((*Condition)(nil)).Elem())
   367  	types.Add("del:DelegationRestrictionType", reflect.TypeOf((*DelegateRestriction)(nil)).Elem())
   368  	types.Add("rsa:RenewRestrictionType", reflect.TypeOf((*RenewRestriction)(nil)).Elem())
   369  }
   370  
   371  type Conditions struct {
   372  	XMLName          xml.Name
   373  	NotBefore        string            `xml:",attr"`
   374  	NotOnOrAfter     string            `xml:",attr"`
   375  	ProxyRestriction *ProxyRestriction `xml:",omitempty"`
   376  	Condition        []BaseCondition   `xml:",omitempty"`
   377  }
   378  
   379  func (c *Conditions) C14N() string {
   380  	names := []*xml.Name{
   381  		&c.XMLName,
   382  	}
   383  
   384  	if c.ProxyRestriction != nil {
   385  		names = append(names, &c.ProxyRestriction.XMLName)
   386  	}
   387  
   388  	for i := range c.Condition {
   389  		switch r := c.Condition[i].(type) {
   390  		case *DelegateRestriction:
   391  			names = append(names, &r.XMLName, &r.Delegate.NameID.XMLName)
   392  			r.NS = XSI
   393  			r.Type = "del:DelegationRestrictionType"
   394  			r.Delegate.NS = r.Delegate.XMLName.Space
   395  			r.Delegate.XMLName = xml.Name{Local: "del:Delegate"}
   396  		case *RenewRestriction:
   397  			names = append(names, &r.XMLName)
   398  			r.NS = XSI
   399  			r.Type = "rsa:RenewRestrictionType"
   400  		}
   401  	}
   402  
   403  	return mkns("saml2", c, names...)
   404  }
   405  
   406  type ProxyRestriction struct {
   407  	XMLName xml.Name
   408  	Count   int32 `xml:",attr"`
   409  }
   410  
   411  type RenewRestriction struct {
   412  	XMLName xml.Name
   413  	NS      string `xml:"xmlns:xsi,attr,omitempty"`
   414  	Count   int32  `xml:",attr"`
   415  	Condition
   416  }
   417  
   418  type Delegate struct {
   419  	XMLName           xml.Name
   420  	NS                string `xml:"xmlns:del,attr,omitempty"`
   421  	DelegationInstant string `xml:",attr"`
   422  	NameID            NameID
   423  }
   424  
   425  type DelegateRestriction struct {
   426  	XMLName xml.Name
   427  	NS      string `xml:"xmlns:xsi,attr,omitempty"`
   428  	Condition
   429  	Delegate Delegate
   430  }
   431  
   432  type AuthnStatement struct {
   433  	XMLName      xml.Name
   434  	AuthnInstant string `xml:",attr"`
   435  	AuthnContext struct {
   436  		XMLName              xml.Name
   437  		AuthnContextClassRef struct {
   438  			XMLName xml.Name
   439  			Value   string `xml:",innerxml"`
   440  		}
   441  	}
   442  }
   443  
   444  func (a *AuthnStatement) C14N() string {
   445  	return mkns("saml2", a, &a.XMLName, &a.AuthnContext.XMLName, &a.AuthnContext.AuthnContextClassRef.XMLName)
   446  }
   447  
   448  type AttributeStatement struct {
   449  	XMLName   xml.Name
   450  	Attribute []Attribute
   451  }
   452  
   453  func (a *AttributeStatement) C14N() string {
   454  	c14n := []string{"<saml2:AttributeStatement>"}
   455  	for i := range a.Attribute {
   456  		c14n = append(c14n, a.Attribute[i].C14N())
   457  	}
   458  	c14n = append(c14n, "</saml2:AttributeStatement>")
   459  	return strings.Join(c14n, "")
   460  }
   461  
   462  type AttributeValue struct {
   463  	XMLName xml.Name
   464  	Type    string `xml:"type,attr,typeattr"`
   465  	Value   string `xml:",innerxml"`
   466  }
   467  
   468  func (a *AttributeValue) C14N() string {
   469  	return fmt.Sprintf(`<saml2:AttributeValue xmlns:xsi="%s" xsi:type="%s">%s</saml2:AttributeValue>`, XSI, a.Type, a.Value)
   470  }
   471  
   472  type Attribute struct {
   473  	XMLName        xml.Name
   474  	FriendlyName   string `xml:",attr"`
   475  	Name           string `xml:",attr"`
   476  	NameFormat     string `xml:",attr"`
   477  	AttributeValue []AttributeValue
   478  }
   479  
   480  func (a *Attribute) C14N() string {
   481  	c14n := []string{
   482  		fmt.Sprintf(`<saml2:Attribute FriendlyName="%s" Name="%s" NameFormat="%s">`, a.FriendlyName, a.Name, a.NameFormat),
   483  	}
   484  
   485  	for i := range a.AttributeValue {
   486  		c14n = append(c14n, a.AttributeValue[i].C14N())
   487  	}
   488  
   489  	c14n = append(c14n, `</saml2:Attribute>`)
   490  
   491  	return strings.Join(c14n, "")
   492  }
   493  
   494  type Lifetime struct {
   495  	Created string `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Created"`
   496  	Expires string `xml:"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Expires"`
   497  }
   498  
   499  func (t *Lifetime) C14N() string {
   500  	return fmt.Sprintf(`<Lifetime><wsu:Created>%s</wsu:Created><wsu:Expires>%s</wsu:Expires></Lifetime>`, t.Created, t.Expires)
   501  }
   502  
   503  type Renewing struct {
   504  	Allow bool `xml:",attr"`
   505  	OK    bool `xml:",attr"`
   506  }
   507  
   508  type UseKey struct {
   509  	Sig string `xml:",attr"`
   510  }
   511  
   512  type Target struct {
   513  	Token string `xml:",innerxml"`
   514  }
   515  
   516  type RequestSecurityToken struct {
   517  	TokenType          string    `xml:",omitempty"`
   518  	RequestType        string    `xml:",omitempty"`
   519  	Lifetime           *Lifetime `xml:",omitempty"`
   520  	Renewing           *Renewing `xml:",omitempty"`
   521  	Delegatable        bool      `xml:",omitempty"`
   522  	KeyType            string    `xml:",omitempty"`
   523  	SignatureAlgorithm string    `xml:",omitempty"`
   524  	UseKey             *UseKey   `xml:",omitempty"`
   525  	ActAs              *Target   `xml:",omitempty"`
   526  	ValidateTarget     *Target   `xml:",omitempty"`
   527  	RenewTarget        *Target   `xml:",omitempty"`
   528  }
   529  
   530  func Unmarshal(data []byte, v any) error {
   531  	dec := xml.NewDecoder(bytes.NewReader(data))
   532  	dec.TypeFunc = types.TypeFunc()
   533  	return dec.Decode(v)
   534  }
   535  
   536  // toString returns an XML encoded RequestSecurityToken.
   537  // When c14n is true, returns the canonicalized ActAs.Assertion which is required to sign the Issue request.
   538  // When c14n is false, returns the original content of the ActAs.Assertion.
   539  // The original content must be used within the request Body, as it has its own signature.
   540  func (r *RequestSecurityToken) toString(c14n bool) string {
   541  	actas := ""
   542  	if r.ActAs != nil {
   543  		token := r.ActAs.Token
   544  		if c14n {
   545  			var a Assertion
   546  			err := Unmarshal([]byte(r.ActAs.Token), &a)
   547  			if err != nil {
   548  				log.Printf("decode ActAs: %s", err)
   549  			}
   550  			token = a.C14N()
   551  		}
   552  
   553  		actas = fmt.Sprintf(`<wst:ActAs xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200802">%s</wst:ActAs>`, token)
   554  	}
   555  
   556  	body := []string{
   557  		fmt.Sprintf(`<RequestSecurityToken xmlns="http://docs.oasis-open.org/ws-sx/ws-trust/200512">`),
   558  		fmt.Sprintf(`<TokenType>%s</TokenType>`, r.TokenType),
   559  		fmt.Sprintf(`<RequestType>%s</RequestType>`, r.RequestType),
   560  		r.Lifetime.C14N(),
   561  	}
   562  
   563  	if r.RenewTarget == nil {
   564  		body = append(body,
   565  			fmt.Sprintf(`<Renewing Allow="%t" OK="%t"></Renewing>`, r.Renewing.Allow, r.Renewing.OK),
   566  			fmt.Sprintf(`<Delegatable>%t</Delegatable>`, r.Delegatable),
   567  			actas,
   568  			fmt.Sprintf(`<KeyType>%s</KeyType>`, r.KeyType),
   569  			fmt.Sprintf(`<SignatureAlgorithm>%s</SignatureAlgorithm>`, r.SignatureAlgorithm),
   570  			fmt.Sprintf(`<UseKey Sig="%s"></UseKey>`, r.UseKey.Sig))
   571  	} else {
   572  		token := r.RenewTarget.Token
   573  		if c14n {
   574  			var a Assertion
   575  			err := Unmarshal([]byte(r.RenewTarget.Token), &a)
   576  			if err != nil {
   577  				log.Printf("decode Renew: %s", err)
   578  			}
   579  			token = a.C14N()
   580  		}
   581  
   582  		body = append(body,
   583  			fmt.Sprintf(`<UseKey Sig="%s"></UseKey>`, r.UseKey.Sig),
   584  			fmt.Sprintf(`<RenewTarget>%s</RenewTarget>`, token))
   585  	}
   586  
   587  	return strings.Join(append(body, `</RequestSecurityToken>`), "")
   588  }
   589  
   590  func (r *RequestSecurityToken) C14N() string {
   591  	return r.toString(true)
   592  }
   593  
   594  func (r *RequestSecurityToken) String() string {
   595  	return r.toString(false)
   596  }
   597  
   598  type RequestSecurityTokenResponseCollection struct {
   599  	RequestSecurityTokenResponse RequestSecurityTokenResponse
   600  }
   601  
   602  type RequestSecurityTokenResponse struct {
   603  	RequestedSecurityToken RequestedSecurityToken
   604  	Lifetime               *Lifetime `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 Lifetime"`
   605  }
   606  
   607  type RequestedSecurityToken struct {
   608  	Assertion string `xml:",innerxml"`
   609  }
   610  
   611  type RequestSecurityTokenBody struct {
   612  	Req    *RequestSecurityToken                   `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityToken,omitempty"`
   613  	Res    *RequestSecurityTokenResponseCollection `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityTokenResponseCollection,omitempty"`
   614  	Fault_ *soap.Fault                             `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
   615  }
   616  
   617  func (b *RequestSecurityTokenBody) Fault() *soap.Fault { return b.Fault_ }
   618  
   619  func (b *RequestSecurityTokenBody) RequestSecurityToken() *RequestSecurityToken { return b.Req }
   620  
   621  func (r *RequestSecurityToken) Action() string {
   622  	kind := path.Base(r.RequestType)
   623  	return "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/" + kind
   624  }
   625  
   626  func Issue(ctx context.Context, r soap.RoundTripper, req *RequestSecurityToken) (*RequestSecurityTokenResponseCollection, error) {
   627  	var reqBody, resBody RequestSecurityTokenBody
   628  
   629  	reqBody.Req = req
   630  
   631  	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
   632  		return nil, err
   633  	}
   634  
   635  	return resBody.Res, nil
   636  }
   637  
   638  type RenewSecurityTokenBody struct {
   639  	Req    *RequestSecurityToken         `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityToken,omitempty"`
   640  	Res    *RequestSecurityTokenResponse `xml:"http://docs.oasis-open.org/ws-sx/ws-trust/200512 RequestSecurityTokenResponse,omitempty"`
   641  	Fault_ *soap.Fault                   `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
   642  }
   643  
   644  func (b *RenewSecurityTokenBody) Fault() *soap.Fault { return b.Fault_ }
   645  
   646  func (b *RenewSecurityTokenBody) RequestSecurityToken() *RequestSecurityToken { return b.Req }
   647  
   648  func Renew(ctx context.Context, r soap.RoundTripper, req *RequestSecurityToken) (*RequestSecurityTokenResponse, error) {
   649  	var reqBody, resBody RenewSecurityTokenBody
   650  
   651  	reqBody.Req = req
   652  
   653  	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
   654  		return nil, err
   655  	}
   656  
   657  	return resBody.Res, nil
   658  }
   659  
   660  // Marshal panics if xml.Marshal returns an error
   661  func Marshal(val any) string {
   662  	b, err := xml.Marshal(val)
   663  	if err != nil {
   664  		panic(err)
   665  	}
   666  	return string(b)
   667  }
   668  
   669  // mkns prepends the given namespace to xml.Name.Local and returns obj encoded as xml.
   670  // Note that the namespace is required when encoding, but the namespace prefix must not be
   671  // present when decoding as Go's decoding does not handle namespace prefix.
   672  func mkns(ns string, obj any, name ...*xml.Name) string {
   673  	ns += ":"
   674  	for i := range name {
   675  		name[i].Space = ""
   676  		if !strings.HasPrefix(name[i].Local, ns) {
   677  			name[i].Local = ns + name[i].Local
   678  		}
   679  	}
   680  
   681  	return Marshal(obj)
   682  }