зеркало из https://github.com/microsoft/oe-engine.git
allow passing public SSH keys from the command line (#13)
* allow passing public SSH keys from the command line * update docs
This commit is contained in:
Родитель
7a13050aea
Коммит
fc30368d38
|
@ -3,7 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Microsoft/oe-engine/pkg/api"
|
"github.com/Microsoft/oe-engine/pkg/api"
|
||||||
"github.com/Microsoft/oe-engine/pkg/engine"
|
"github.com/Microsoft/oe-engine/pkg/engine"
|
||||||
|
@ -15,13 +17,13 @@ import (
|
||||||
const (
|
const (
|
||||||
generateName = "generate"
|
generateName = "generate"
|
||||||
generateShortDescription = "Generate an Azure Resource Manager template"
|
generateShortDescription = "Generate an Azure Resource Manager template"
|
||||||
generateLongDescription = "Generates an Azure Resource Manager template, parameters file and other assets for a cluster"
|
generateLongDescription = "Generates an Azure Resource Manager template and parameters file"
|
||||||
)
|
)
|
||||||
|
|
||||||
type generateCmd struct {
|
type generateCmd struct {
|
||||||
apimodelPath string
|
apimodelPath string
|
||||||
outputDirectory string // can be auto-determined from clusterDefinition
|
outputDirectory string
|
||||||
classicMode bool
|
sshPubKeys []string
|
||||||
noPrettyPrint bool
|
noPrettyPrint bool
|
||||||
parametersOnly bool
|
parametersOnly bool
|
||||||
|
|
||||||
|
@ -51,8 +53,8 @@ func newGenerateCmd() *cobra.Command {
|
||||||
|
|
||||||
f := generateCmd.Flags()
|
f := generateCmd.Flags()
|
||||||
f.StringVar(&gc.apimodelPath, "api-model", "", "")
|
f.StringVar(&gc.apimodelPath, "api-model", "", "")
|
||||||
f.StringVar(&gc.outputDirectory, "output-directory", "", "output directory (derived from FQDN if absent)")
|
f.StringVar(&gc.outputDirectory, "output-directory", "", "output directory (_output if absent)")
|
||||||
f.BoolVar(&gc.classicMode, "classic-mode", false, "enable classic parameters and outputs")
|
f.StringArrayVar(&gc.sshPubKeys, "ssh-public-key", nil, "SSH public key file path")
|
||||||
f.BoolVar(&gc.noPrettyPrint, "no-pretty-print", false, "skip pretty printing the output")
|
f.BoolVar(&gc.noPrettyPrint, "no-pretty-print", false, "skip pretty printing the output")
|
||||||
f.BoolVar(&gc.parametersOnly, "parameters-only", false, "only output parameters files")
|
f.BoolVar(&gc.parametersOnly, "parameters-only", false, "only output parameters files")
|
||||||
|
|
||||||
|
@ -77,6 +79,17 @@ func (gc *generateCmd) validate(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf(fmt.Sprintf("specified api model does not exist (%s)", gc.apimodelPath))
|
return fmt.Errorf(fmt.Sprintf("specified api model does not exist (%s)", gc.apimodelPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, keyPath := range gc.sshPubKeys {
|
||||||
|
if _, err := os.Stat(keyPath); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf(fmt.Sprintf("ssh public key file %s does not exist", keyPath))
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gc.sshPubKeys[i] = strings.TrimSpace(string(b))
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +97,7 @@ func (gc *generateCmd) loadAPIModel(cmd *cobra.Command, args []string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
apiloader := &api.Apiloader{}
|
apiloader := &api.Apiloader{}
|
||||||
gc.oe, err = apiloader.LoadOpenEnclaveFromFile(gc.apimodelPath, true, false)
|
gc.oe, err = apiloader.LoadOpenEnclaveFromFile(gc.apimodelPath, true, false, gc.sshPubKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(fmt.Sprintf("error parsing the api model: %s", err.Error()))
|
return fmt.Errorf(fmt.Sprintf("error parsing the api model: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,9 @@ Alternatively, you can download latest release from [here](https://github.com/Mi
|
||||||
|
|
||||||
### Create VM definition file
|
### Create VM definition file
|
||||||
The VM definition file is a JSON-formatted description of the properties of the VMs, such as: compute power, OS image, credentials, etc.
|
The VM definition file is a JSON-formatted description of the properties of the VMs, such as: compute power, OS image, credentials, etc.
|
||||||
|
|
||||||
|
For details, refer to the [Setting properties in the VM definition file](properties.md)
|
||||||
|
|
||||||
The examples below illustrate how to set the various properties.
|
The examples below illustrate how to set the various properties.
|
||||||
|
|
||||||
* [Multi-VM deployment](examples/oe-multi-vm.json) - Deploying multiple VMs
|
* [Multi-VM deployment](examples/oe-multi-vm.json) - Deploying multiple VMs
|
||||||
|
@ -21,13 +24,6 @@ The examples below illustrate how to set the various properties.
|
||||||
* [Linux user password](examples/oe-lnx-passwd.json) - Using password authentication instead of SSH on Linux
|
* [Linux user password](examples/oe-lnx-passwd.json) - Using password authentication instead of SSH on Linux
|
||||||
* [Windows OpenSSH](examples/oe-win-ssh.json) - Installing and configuring OpenSSH on Windows
|
* [Windows OpenSSH](examples/oe-win-ssh.json) - Installing and configuring OpenSSH on Windows
|
||||||
|
|
||||||
The table below summarizes enumerated properties:
|
|
||||||
|
|
||||||
| Property | Key | Values |
|
|
||||||
| ------ | ------ |------ |
|
|
||||||
| OS | `osImageName` | `UbuntuServer_16.04` `WindowsServer_2016` |
|
|
||||||
| Compute| `vmSize` | `Standard_DC2s` `Standard_DC4s` |
|
|
||||||
|
|
||||||
## Generate deployment template
|
## Generate deployment template
|
||||||
|
|
||||||
`oe-engine` generates 3 files:
|
`oe-engine` generates 3 files:
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
# Setting properties in the VM definition file
|
||||||
|
|
||||||
|
This document describes VM properties, configurable in the VM definition file
|
||||||
|
|
||||||
|
### VM name
|
||||||
|
Specifies VM name.
|
||||||
|
|
||||||
|
* Path: `properties/vmProfiles[]/name`
|
||||||
|
* Value: string (follows the rules of underlying OS)
|
||||||
|
|
||||||
|
### OS image
|
||||||
|
Specifies the type and the version of the operating system.
|
||||||
|
|
||||||
|
* Path: `properties/vmProfiles[]/osImageName`
|
||||||
|
* Values:
|
||||||
|
* `UbuntuServer_16.04`
|
||||||
|
* `WindowsServer_2016`
|
||||||
|
|
||||||
|
### OS disk type
|
||||||
|
Specifies OS disk characteristics.
|
||||||
|
|
||||||
|
* Path: `properties/vmProfiles[]/osImageName`
|
||||||
|
* Values:
|
||||||
|
* `Premium_LRS` - Premium SSD
|
||||||
|
* `StandardSSD_LRS` - Standard SSD
|
||||||
|
* `Standard_LRS` - Standard HDD
|
||||||
|
|
||||||
|
### VM compute power
|
||||||
|
Specifies VM compute characteristics
|
||||||
|
|
||||||
|
* Path: `properties/vmProfiles[]/vmSize`
|
||||||
|
* Values:
|
||||||
|
* `Standard_DC2s`
|
||||||
|
* `Standard_DC4s`
|
||||||
|
|
||||||
|
Refer to the [VM sizes in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes) for more details.
|
||||||
|
|
||||||
|
### VM Software
|
||||||
|
Indicates whether Open Enclave SDK and its dependencies should be installed or not.
|
||||||
|
|
||||||
|
* Path: `properties/vmProfiles[]/isVanilla`
|
||||||
|
* Values: boolean
|
||||||
|
* `true` - a vanilla VM. Open Enclave SDK will not be installed
|
||||||
|
* `false` - not a vanilla VM. Open Enclave SDK will be installed and verified
|
||||||
|
|
||||||
|
### Linux credentials
|
||||||
|
If at least one of the VMs runs Linux, `linuxProfile` must be present and contain admin user name and password or public SSH key.
|
||||||
|
Multiple public keys are **supported**.
|
||||||
|
Setting both the password and the public key(s) is **not allowed**.
|
||||||
|
|
||||||
|
* Path: `properties/linuxProfile/adminUsername`
|
||||||
|
* Value: string
|
||||||
|
|
||||||
|
* Path: `properties/linuxProfile/adminPassword`
|
||||||
|
* Value: string
|
||||||
|
|
||||||
|
* Path: `properties/linuxProfile/sshPublicKeys[]/keyData`
|
||||||
|
* Value: public SSH key
|
||||||
|
|
||||||
|
The public SSH key(s) could also be set from the command line using `--ssh-public-key` argument.
|
||||||
|
```sh
|
||||||
|
oe-engine generate oe-vm.json --ssh-public-key .ssh/id_rsa1.pub --ssh-public-key .ssh/id_rsa2.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows credentials
|
||||||
|
If at least one of the VMs runs Windows, `windowsProfile` must be present and contain admin user name and password.
|
||||||
|
|
||||||
|
* Path: `properties/windowsProfile/adminUsername`
|
||||||
|
* Value: string
|
||||||
|
|
||||||
|
* Path: `properties/windowsProfile/adminPassword`
|
||||||
|
* Value: string
|
|
@ -15,17 +15,17 @@ type Apiloader struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadOpenEnclaveFromFile loads an OE API Model from a JSON file
|
// LoadOpenEnclaveFromFile loads an OE API Model from a JSON file
|
||||||
func (a *Apiloader) LoadOpenEnclaveFromFile(jsonFile string, validate, isUpdate bool) (*OpenEnclave, error) {
|
func (a *Apiloader) LoadOpenEnclaveFromFile(jsonFile string, validate, isUpdate bool, sshPubKeys []string) (*OpenEnclave, error) {
|
||||||
contents, e := ioutil.ReadFile(jsonFile)
|
contents, e := ioutil.ReadFile(jsonFile)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, fmt.Errorf("error reading file %s: %s", jsonFile, e.Error())
|
return nil, fmt.Errorf("error reading file %s: %s", jsonFile, e.Error())
|
||||||
}
|
}
|
||||||
return a.DeserializeOpenEnclave(contents, validate, isUpdate)
|
return a.DeserializeOpenEnclave(contents, validate, isUpdate, sshPubKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeserializeOpenEnclave loads an ACS Cluster API Model, validates it, and returns the unversioned representation
|
// DeserializeOpenEnclave loads an ACS Cluster API Model, validates it, and returns the unversioned representation
|
||||||
func (a *Apiloader) DeserializeOpenEnclave(contents []byte, validate, isUpdate bool) (*OpenEnclave, error) {
|
func (a *Apiloader) DeserializeOpenEnclave(contents []byte, validate, isUpdate bool, sshPubKeys []string) (*OpenEnclave, error) {
|
||||||
oe, err := a.LoadOpenEnclave(contents, validate, isUpdate)
|
oe, err := a.LoadOpenEnclave(contents, validate, isUpdate, sshPubKeys)
|
||||||
if oe == nil || err != nil {
|
if oe == nil || err != nil {
|
||||||
log.Infof("Error returned by LoadOpenEnclave: %+v", err)
|
log.Infof("Error returned by LoadOpenEnclave: %+v", err)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ func (a *Apiloader) DeserializeOpenEnclave(contents []byte, validate, isUpdate b
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadOpenEnclave loads and validates an OE API Model
|
// LoadOpenEnclave loads and validates an OE API Model
|
||||||
func (a *Apiloader) LoadOpenEnclave(contents []byte, validate, isUpdate bool) (*OpenEnclave, error) {
|
func (a *Apiloader) LoadOpenEnclave(contents []byte, validate, isUpdate bool, sshPubKeys []string) (*OpenEnclave, error) {
|
||||||
oe := &OpenEnclave{}
|
oe := &OpenEnclave{}
|
||||||
if e := json.Unmarshal(contents, oe); e != nil {
|
if e := json.Unmarshal(contents, oe); e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
|
@ -41,6 +41,12 @@ func (a *Apiloader) LoadOpenEnclave(contents []byte, validate, isUpdate bool) (*
|
||||||
if e := checkJSONKeys(contents, reflect.TypeOf(*oe)); e != nil {
|
if e := checkJSONKeys(contents, reflect.TypeOf(*oe)); e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
// add SSH public keys from command line arguments
|
||||||
|
if oe.Properties.LinuxProfile != nil {
|
||||||
|
for _, key := range sshPubKeys {
|
||||||
|
oe.Properties.LinuxProfile.SSHPubKeys = append(oe.Properties.LinuxProfile.SSHPubKeys, &PublicKey{KeyData: key})
|
||||||
|
}
|
||||||
|
}
|
||||||
if e := oe.Properties.Validate(isUpdate); validate && e != nil {
|
if e := oe.Properties.Validate(isUpdate); validate && e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче