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

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