func (s *withoutStateServerSuite) TestProvisioningInfoPermissions(c *gc.C) { // Login as a machine agent for machine 0. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false anAuthorizer.Tag = s.machines[0].Tag() aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag()}, {Tag: s.machines[0].Tag() + "-lxc-0"}, {Tag: "machine-42"}, {Tag: s.machines[1].Tag()}, {Tag: "service-bar"}, }} // Only machine 0 and containers therein can be accessed. results, err := aProvisioner.ProvisioningInfo(args) c.Assert(results, gc.DeepEquals, params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{ {Result: ¶ms.ProvisioningInfo{ Series: "quantal", Networks: []string{}, }}, {Error: apiservertesting.NotFoundError("machine 0/lxc/0")}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutStateServerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) { // Machines where there's permission issues are omitted. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false anAuthorizer.Tag = "machine-1" aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) err = s.machines[0].SetStatus(params.StatusStarted, "blah", nil) c.Assert(err, gc.IsNil) err = s.machines[1].SetStatus(params.StatusError, "transient error", params.StatusData{"transient": true, "foo": "bar"}) c.Assert(err, gc.IsNil) err = s.machines[2].SetStatus(params.StatusError, "error", params.StatusData{"transient": false}) c.Assert(err, gc.IsNil) err = s.machines[3].SetStatus(params.StatusError, "error", nil) c.Assert(err, gc.IsNil) result, err := aProvisioner.MachinesWithTransientErrors() c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.StatusResults{ Results: []params.StatusResult{ {Id: "1", Life: "alive", Status: "error", Info: "transient error", Data: params.StatusData{"transient": true, "foo": "bar"}}, }, }) }
func (s *withoutStateServerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) { anAuthorizer := s.authorizer anAuthorizer.Tag = "machine-1" anAuthorizer.EnvironManager = false anAuthorizer.MachineAgent = true provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Check(err, gc.IsNil) args := params.Entities{Entities: []params.Entity{ {Tag: "machine-0"}, {Tag: "machine-1"}, {Tag: "machine-42"}, {Tag: "machine-0-lxc-99"}, {Tag: "machine-1-lxc-99"}, {Tag: "machine-1-lxc-99-lxc-100"}, }} result, err := provisioner.DistributionGroup(args) c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ Results: []params.DistributionGroupResult{ {Error: apiservertesting.ErrUnauthorized}, {Result: []instance.Id{}}, {Error: apiservertesting.ErrUnauthorized}, // only a machine agent for the container or its // parent may access it. {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.NotFoundError("machine 1/lxc/99")}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) { s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait) c.Assert(s.resources.Count(), gc.Equals, 0) _, err := s.provisioner.WatchMachineErrorRetry() c.Assert(err, gc.IsNil) // Verify the resources were registered and stop them when done. c.Assert(s.resources.Count(), gc.Equals, 1) resource := s.resources.Get("1") defer statetesting.AssertStop(c, resource) // Check that the Watch has consumed the initial event ("returned" // in the Watch call) wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) wc.AssertNoChange() // We should now get a time triggered change. wc.AssertOneChange() // Make sure WatchMachineErrorRetry fails with a machine agent login. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) result, err := aProvisioner.WatchMachineErrorRetry() c.Assert(err, gc.ErrorMatches, "permission denied") c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{}) }
func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(c *gc.C) { // Login as a machine agent for machine 0. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false anAuthorizer.Tag = s.machines[0].Tag() aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) args := params.MachineContainersParams{ Params: []params.MachineContainers{{ MachineTag: "machine-0", ContainerTypes: []instance.ContainerType{instance.LXC}, }, { MachineTag: "machine-1", ContainerTypes: []instance.ContainerType{instance.LXC}, }, { MachineTag: "machine-42", ContainerTypes: []instance.ContainerType{instance.LXC}, }, }, } // Only machine 0 can have it's containers updated. results, err := aProvisioner.SetSupportedContainers(args) c.Assert(results, gc.DeepEquals, params.ErrorResults{ Results: []params.ErrorResult{ {Error: nil}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) { c.Assert(s.resources.Count(), gc.Equals, 0) got, err := s.provisioner.WatchEnvironMachines() c.Assert(err, gc.IsNil) want := params.StringsWatchResult{ StringsWatcherId: "1", Changes: []string{"0", "1", "2", "3", "4"}, } c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId) c.Assert(got.Changes, jc.SameContents, want.Changes) // Verify the resources were registered and stop them when done. c.Assert(s.resources.Count(), gc.Equals, 1) resource := s.resources.Get("1") defer statetesting.AssertStop(c, resource) // Check that the Watch has consumed the initial event ("returned" // in the Watch call) wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) wc.AssertNoChange() // Make sure WatchEnvironMachines fails with a machine agent login. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) result, err := aProvisioner.WatchEnvironMachines() c.Assert(err, gc.ErrorMatches, "permission denied") c.Assert(result, gc.DeepEquals, params.StringsWatchResult{}) }
func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) { anAuthorizer := s.authorizer anAuthorizer.MachineAgent = false anAuthorizer.EnvironManager = true // Works with an environment manager, which is not a machine agent. aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) // But fails with neither a machine agent or an environment manager. anAuthorizer.EnvironManager = false aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.NotNil) c.Assert(aProvisioner, gc.IsNil) c.Assert(err, gc.ErrorMatches, "permission denied") }
// Provisioner returns an object that provides access to the // Provisioner API facade. The id argument is reserved for future use // and currently needs to be empty. func (r *srvRoot) Provisioner(id string) (*provisioner.ProvisionerAPI, error) { if id != "" { // Safeguard id for possible future use. return nil, common.ErrBadId } return provisioner.NewProvisionerAPI(r.srv.state, r.resources, r) }
func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) { // Now test it with a non-environment manager and make sure // the secret attributes are masked. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets) }
func (s *withoutStateServerSuite) TestToolsRefusesWrongAgent(c *gc.C) { anAuthorizer := s.authorizer anAuthorizer.Tag = "machine-12354" anAuthorizer.EnvironManager = false anAuthorizer.MachineAgent = true aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Check(err, gc.IsNil) args := params.Entities{ Entities: []params.Entity{{Tag: s.machines[0].Tag()}}, } results, err := aProvisioner.Tools(args) // It is not an error to make the request, but the specific item is rejected c.Assert(err, gc.IsNil) c.Check(results.Results, gc.HasLen, 1) toolResult := results.Results[0] c.Assert(toolResult.Error, gc.DeepEquals, apiservertesting.ErrUnauthorized) }
func (s *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) { s.JujuConnSuite.SetUpTest(c) // Reset previous machines (if any) and create 3 machines // for the tests, plus an optional state server machine. s.machines = nil // Note that the specific machine ids allocated are assumed // to be numerically consecutive from zero. if withStateServer { s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State)) } for i := 0; i < 5; i++ { machine, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Check(err, gc.IsNil) s.machines = append(s.machines, machine) } // Create a FakeAuthorizer so we can check permissions, // set up assuming we logged in as the environment manager. s.authorizer = apiservertesting.FakeAuthorizer{ LoggedIn: true, EnvironManager: true, } // Create the resource registry separately to track invocations to // Register. s.resources = common.NewResources() // Create a provisioner API for the machine. provisionerAPI, err := provisioner.NewProvisionerAPI( s.State, s.resources, s.authorizer, ) c.Assert(err, gc.IsNil) s.provisioner = provisionerAPI }
func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) { // NOTE: This and the next call serve to test the two // different authorization schemes: // 1. Machine agents can access their own machine and // any container that has their own machine as parent; // 2. Environment managers can access any machine without // a parent. // There's no need to repeat this test for each method, // because the authorization logic is common. // Login as a machine agent for machine 0. anAuthorizer := s.authorizer anAuthorizer.MachineAgent = true anAuthorizer.EnvironManager = false anAuthorizer.Tag = s.machines[0].Tag() aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) // Make the machine dead before trying to add containers. err = s.machines[0].EnsureDead() c.Assert(err, gc.IsNil) // Create some containers to work on. template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, } var containers []*state.Machine for i := 0; i < 3; i++ { container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC) c.Check(err, gc.IsNil) containers = append(containers, container) } // Make one container dead. err = containers[1].EnsureDead() c.Assert(err, gc.IsNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag()}, {Tag: s.machines[1].Tag()}, {Tag: containers[0].Tag()}, {Tag: containers[1].Tag()}, {Tag: containers[2].Tag()}, {Tag: "machine-42"}, {Tag: "unit-foo-0"}, {Tag: "service-bar"}, }} result, err := aProvisioner.Life(args) c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.LifeResults{ Results: []params.LifeResult{ {Life: "dead"}, {Error: apiservertesting.ErrUnauthorized}, {Life: "alive"}, {Life: "dead"}, {Life: "alive"}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }