func (a *GenRandomAction) Run(s *State) error { if a.Length == 0 { a.Length = 16 } data := interpolate(s, a.Data) if data == "" { switch a.Encoding { case "", "hex": data = random.Hex(a.Length) case "base64": data = base64.StdEncoding.EncodeToString(random.Bytes(a.Length)) case "base64safe": data = random.Base64(a.Length) case "uuid": data = random.UUID() default: return fmt.Errorf("bootstrap: unknown random type: %q", a.Encoding) } } s.StepData[a.ID] = &RandomData{Data: data} if a.ControllerKey { s.SetControllerKey(data) } return nil }
func (b *azureBackend) Put(tx *postgres.DBTx, info FileInfo, r io.Reader, appendBlob bool) error { if appendBlob { // TODO(titanous): This is a hack, we should modify the block list. existing, err := b.Open(tx, info, false) if err != nil { return err } r = io.MultiReader(existing, r) } info.ExternalID = random.UUID() if err := tx.Exec("UPDATE files SET external_id = $2 WHERE file_id = $1", info.ID, info.ExternalID); err != nil { return err } // Create blob that will be filled with blocks if err := b.client.CreateBlockBlob(b.container, info.ExternalID); err != nil { return err } var blocks []storage.Block // Create blocks buf := make([]byte, azureMaxBlockSize) for { n, err := io.ReadFull(r, buf) if err == io.EOF { break } if err != nil && err != io.ErrUnexpectedEOF { return err } data := buf[:n] md5sum := md5.Sum(data) blockID := base64.StdEncoding.EncodeToString(random.Bytes(16)) if err := b.client.PutBlockWithLength( b.container, info.ExternalID, blockID, uint64(n), bytes.NewReader(data), map[string]string{"Content-MD5": base64.StdEncoding.EncodeToString(md5sum[:])}, ); err != nil { return err } blocks = append(blocks, storage.Block{ID: blockID, Status: storage.BlockStatusUncommitted}) if err == io.ErrUnexpectedEOF { break } } // Save the list of blocks to the blob return b.client.PutBlockList(b.container, info.ExternalID, blocks) }
func createBridge(name, network, natIface string) (*Bridge, error) { ipAddr, ipNet, err := net.ParseCIDR(network) if err != nil { return nil, err } if err := netlink.CreateBridge(name, true); err != nil { return nil, err } iface, err := net.InterfaceByName(name) if err != nil { return nil, err } // We need to explicitly assign the MAC address to avoid it changing to a lower value // See: https://github.com/flynn/flynn/issues/223 b := random.Bytes(5) mac := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4]) if err := netlink.NetworkSetMacAddress(iface, mac); err != nil { return nil, err } if err := netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil { return nil, err } if err := netlink.NetworkLinkUp(iface); err != nil { return nil, err } if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil { return nil, err } if err := setupIPTables(name, natIface); err != nil { return nil, err } bridge := &Bridge{ name: name, iface: iface, ipAddr: ipAddr, ipNet: ipNet, alloc: ipallocator.New(), } bridge.alloc.RequestIP(ipNet, ipAddr) return bridge, nil }
func (i *Instance) Start() error { i.writeInterfaceConfig() macRand := random.Bytes(3) macaddr := fmt.Sprintf("52:54:00:%02x:%02x:%02x", macRand[0], macRand[1], macRand[2]) i.Args = append(i.Args, "-enable-kvm", "-kernel", i.Kernel, "-append", `"root=/dev/sda"`, "-netdev", "tap,id=vmnic,ifname="+i.tap.Name+",script=no,downscript=no", "-device", "virtio-net,netdev=vmnic,mac="+macaddr, "-virtfs", "fsdriver=local,path="+i.netFS+",security_model=passthrough,readonly,mount_tag=netfs", "-virtfs", "fsdriver=local,path="+i.BackupsDir+",security_model=passthrough,readonly,mount_tag=backupsfs", "-nographic", ) if i.Memory != "" { i.Args = append(i.Args, "-m", i.Memory) } if i.Cores > 0 { i.Args = append(i.Args, "-smp", strconv.Itoa(i.Cores)) } for n, d := range i.Drives { if d.COW { fs, err := i.createCOW(d.FS, d.Temp) if err != nil { i.cleanup() return err } d.FS = fs } i.Args = append(i.Args, fmt.Sprintf("-%s", n), d.FS) } i.cmd = exec.Command("sudo", append([]string{"-u", fmt.Sprintf("#%d", i.User), "-g", fmt.Sprintf("#%d", i.Group), "-H", "/usr/bin/qemu-system-x86_64"}, i.Args...)...) i.cmd.Stdout = i.Out i.cmd.Stderr = i.Out var err error if err = i.cmd.Start(); err != nil { i.cleanup() } return err }
func (v *vm) Start() error { v.writeInterfaceConfig() macRand := random.Bytes(3) macaddr := fmt.Sprintf("52:54:00:%02x:%02x:%02x", macRand[0], macRand[1], macRand[2]) v.Args = append(v.Args, "-enable-kvm", "-kernel", v.Kernel, "-append", `"root=/dev/sda"`, "-net", "nic,macaddr="+macaddr, "-net", "tap,ifname="+v.tap.Name+",script=no,downscript=no", "-virtfs", "fsdriver=local,path="+v.netFS+",security_model=passthrough,readonly,mount_tag=netfs", "-nographic", ) if v.Memory != "" { v.Args = append(v.Args, "-m", v.Memory) } if v.Cores > 0 { v.Args = append(v.Args, "-smp", strconv.Itoa(v.Cores)) } var err error for i, d := range v.Drives { if d.COW { fs, err := v.createCOW(d.FS, d.Temp) if err != nil { v.cleanup() return err } d.FS = fs } v.Args = append(v.Args, fmt.Sprintf("-%s", i), d.FS) } v.cmd = exec.Command("sudo", append([]string{"-u", fmt.Sprintf("#%d", v.User), "-g", fmt.Sprintf("#%d", v.Group), "-H", "/usr/bin/qemu-system-x86_64"}, v.Args...)...) v.cmd.Stdout = v.Out v.cmd.Stderr = v.Out if err = v.cmd.Start(); err != nil { v.cleanup() } return err }
func (s *SchedulerSuite) TestTCPApp(t *c.C) { app, _ := s.createApp(t) stream, err := s.controllerClient(t).StreamJobEvents(app.ID, 0) t.Assert(err, c.IsNil) defer stream.Close() t.Assert(flynn(t, "/", "-a", app.Name, "scale", "echoer=1"), Succeeds) newRoute := flynn(t, "/", "-a", app.Name, "route", "add", "tcp", "-s", "echo-service") t.Assert(newRoute, Succeeds) t.Assert(newRoute.Output, Matches, `.+ on port \d+`) str := strings.Split(strings.TrimSpace(string(newRoute.Output)), " ") port := str[len(str)-1] waitForJobEvents(t, stream.Events, jobEvents{"echoer": {"up": 1}}) // use Attempts to give the processes time to start if err := Attempts.Run(func() error { servAddr := routerIP + ":" + port conn, err := net.Dial("tcp", servAddr) if err != nil { return err } defer conn.Close() echo := random.Bytes(16) _, err = conn.Write(echo) if err != nil { return err } reply := make([]byte, 16) _, err = conn.Read(reply) if err != nil { return err } t.Assert(reply, c.DeepEquals, echo) return nil }); err != nil { t.Fatal(err) } }
// ConfigureNetworking is called once during host startup and passed the // strategy and identifier of the networking coordinatior job. Currently the // only strategy implemented uses flannel. func (l *LibvirtLXCBackend) ConfigureNetworking(config *host.NetworkConfig) error { var err error l.bridgeAddr, l.bridgeNet, err = net.ParseCIDR(config.Subnet) if err != nil { return err } l.ipalloc.RequestIP(l.bridgeNet, l.bridgeAddr) err = netlink.CreateBridge(bridgeName, false) bridgeExists := os.IsExist(err) if err != nil && !bridgeExists { return err } bridge, err := net.InterfaceByName(bridgeName) if err != nil { return err } if !bridgeExists { // We need to explicitly assign the MAC address to avoid it changing to a lower value // See: https://github.com/flynn/flynn/issues/223 b := random.Bytes(5) bridgeMAC := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4]) if err := netlink.NetworkSetMacAddress(bridge, bridgeMAC); err != nil { return err } } currAddrs, err := bridge.Addrs() if err != nil { return err } setIP := true for _, addr := range currAddrs { ip, net, _ := net.ParseCIDR(addr.String()) if ip.Equal(l.bridgeAddr) && net.String() == l.bridgeNet.String() { setIP = false } else { if err := netlink.NetworkLinkDelIp(bridge, ip, net); err != nil { return err } } } if setIP { if err := netlink.NetworkLinkAddIp(bridge, l.bridgeAddr, l.bridgeNet); err != nil { return err } } if err := netlink.NetworkLinkUp(bridge); err != nil { return err } network, err := l.libvirt.LookupNetworkByName(libvirtNetName) if err != nil { // network doesn't exist networkConfig := <.Network{ Name: libvirtNetName, Bridge: lt.Bridge{Name: bridgeName}, Forward: lt.Forward{Mode: "bridge"}, } network, err = l.libvirt.NetworkDefineXML(string(networkConfig.XML())) if err != nil { return err } } active, err := network.IsActive() if err != nil { return err } if !active { if err := network.Create(); err != nil { return err } } if defaultNet, err := l.libvirt.LookupNetworkByName("default"); err == nil { // The default network causes dnsmasq to run and bind to all interfaces, // including ours. This prevents discoverd from binding its DNS server. // We don't use it, so destroy it if it exists. defaultNet.Destroy() } // enable IP forwarding if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil { return err } // Set up iptables for outbound traffic masquerading from containers to the // rest of the network. if err := iptables.EnableOutboundNAT(bridgeName, l.bridgeNet.String()); err != nil { return err } // Read DNS config, discoverd uses the nameservers dnsConf, err := dns.ClientConfigFromFile("/etc/resolv.conf") if err != nil { return err } config.Resolvers = dnsConf.Servers // Write a resolv.conf to be bind-mounted into containers pointing at the // future discoverd DNS listener if err := os.MkdirAll("/etc/flynn", 0755); err != nil { return err } var resolvSearch string if len(dnsConf.Search) > 0 { resolvSearch = fmt.Sprintf("search %s\n", strings.Join(dnsConf.Search, " ")) } if err := ioutil.WriteFile("/etc/flynn/resolv.conf", []byte(fmt.Sprintf("%snameserver %s\n", resolvSearch, l.bridgeAddr.String())), 0644); err != nil { return err } l.resolvConf = "/etc/flynn/resolv.conf" // Allocate IPs for running jobs for i, container := range l.containers { if !container.job.Config.HostNetwork { var err error l.containers[i].IP, err = l.ipalloc.RequestIP(l.bridgeNet, container.IP) if err != nil { grohl.Log(grohl.Data{"fn": "ConfigureNetworking", "at": "request_ip", "status": "error", "err": err}) } } } close(l.networkConfigured) return nil }
// ConfigureNetworking is called once during host startup and sets up the local // bridge and forwarding rules for containers. func (l *LibcontainerBackend) ConfigureNetworking(config *host.NetworkConfig) error { log := l.logger.New("fn", "ConfigureNetworking") var err error l.bridgeAddr, l.bridgeNet, err = net.ParseCIDR(config.Subnet) if err != nil { return err } l.ipalloc.RequestIP(l.bridgeNet, l.bridgeAddr) err = netlink.CreateBridge(l.bridgeName, false) bridgeExists := os.IsExist(err) if err != nil && !bridgeExists { return err } bridge, err := net.InterfaceByName(l.bridgeName) if err != nil { return err } if !bridgeExists { // We need to explicitly assign the MAC address to avoid it changing to a lower value // See: https://github.com/flynn/flynn/issues/223 b := random.Bytes(5) bridgeMAC := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4]) if err := netlink.NetworkSetMacAddress(bridge, bridgeMAC); err != nil { return err } } currAddrs, err := bridge.Addrs() if err != nil { return err } setIP := true for _, addr := range currAddrs { ip, net, _ := net.ParseCIDR(addr.String()) if ip.Equal(l.bridgeAddr) && net.String() == l.bridgeNet.String() { setIP = false } else { if err := netlink.NetworkLinkDelIp(bridge, ip, net); err != nil { return err } } } if setIP { if err := netlink.NetworkLinkAddIp(bridge, l.bridgeAddr, l.bridgeNet); err != nil { return err } } if err := netlink.NetworkLinkUp(bridge); err != nil { return err } // enable IP forwarding if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil { return err } // Set up iptables for outbound traffic masquerading from containers to the // rest of the network. if err := iptables.EnableOutboundNAT(l.bridgeName, l.bridgeNet.String()); err != nil { return err } // Read DNS config, discoverd uses the nameservers dnsConf, err := dns.ClientConfigFromFile("/etc/resolv.conf") if err != nil { return err } config.Resolvers = dnsConf.Servers // Write a resolv.conf to be bind-mounted into containers pointing at the // future discoverd DNS listener if err := os.MkdirAll("/etc/flynn", 0755); err != nil { return err } var resolvSearch string if len(dnsConf.Search) > 0 { resolvSearch = fmt.Sprintf("search %s\n", strings.Join(dnsConf.Search, " ")) } if err := ioutil.WriteFile("/etc/flynn/resolv.conf", []byte(fmt.Sprintf("%snameserver %s\n", resolvSearch, l.bridgeAddr.String())), 0644); err != nil { return err } l.resolvConf = "/etc/flynn/resolv.conf" // Allocate IPs for running jobs l.containersMtx.Lock() defer l.containersMtx.Unlock() for _, container := range l.containers { if !container.job.Config.HostNetwork { if _, err := l.ipalloc.RequestIP(l.bridgeNet, container.IP); err != nil { log.Error("error requesting ip", "job.id", container.job.ID, "err", err) } } } close(l.networkConfigured) return nil }
func (S) TestNonPatterns(c *C) { const sep = " " var input bytes.Buffer key := genPublicKey(c) keyBytes := bytes.TrimRight(bytes.TrimSpace(ssh.MarshalAuthorizedKey(key)), "\n") // format: host key host1Addr := "101.102.103.72" input.WriteString(host1Addr) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") // format: host key host2Addr := "test.example.com" input.WriteString(host2Addr) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") // format: @flag [host]:port key host3Addr := "3.example.com" host3Port := "2222" input.WriteString("@revoked") input.WriteString(sep) input.WriteString("[" + host3Addr + "]:" + host3Port) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") // format: host,host,host key host4Addr := "4.example.com" host5Addr := "102.101.72.100" host6Addr := "6.example.com" input.WriteString(strings.Join([]string{host4Addr, host5Addr, host6Addr}, ",")) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") // format: host,[host]:port,host key host7Addr := "7.example.com" host8Addr := "102.101.72.100" host8Port := "2223" host9Addr := "9.example.com" input.WriteString(strings.Join([]string{host7Addr, "[" + host8Addr + "]:" + host8Port, host9Addr}, ",")) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") // format: @flag host,host key host10Addr := "10.example.com" host11Addr := "11.example.com" input.WriteString("@revoked") input.WriteString(sep) input.WriteString(strings.Join([]string{host10Addr, host11Addr}, ",")) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") // format: hashed host12Addr := "12.example.com" host12Salt := random.Bytes(16) host12SaltEncoded := base64.StdEncoding.EncodeToString(host12Salt) host12Mac := hmac.New(sha1.New, host12Salt) host12Mac.Write([]byte(host12Addr)) host12MacEncoded := base64.StdEncoding.EncodeToString(host12Mac.Sum(nil)) input.WriteString("|1|" + host12SaltEncoded + "|" + host12MacEncoded) input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") k, err := Unmarshal(bytes.NewReader(input.Bytes())) c.Assert(err, IsNil) // Test HostKeyCallback addr := &net.TCPAddr{ Port: 22, } c.Assert(k.HostKeyCallback(host1Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host2Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host3Addr+":2222", &net.TCPAddr{Port: 2222}, key), Equals, HostRevokedError) c.Assert(k.HostKeyCallback(host4Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host5Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host6Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host7Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host8Addr+":2223", &net.TCPAddr{Port: 2223}, key), IsNil) c.Assert(k.HostKeyCallback(host9Addr+":22", addr, key), IsNil) c.Assert(k.HostKeyCallback(host10Addr+":22", addr, key), Equals, HostRevokedError) c.Assert(k.HostKeyCallback(host11Addr+":22", addr, key), Equals, HostRevokedError) c.Assert(k.HostKeyCallback("notfound.example.com:22", addr, key), Equals, HostNotFoundError) c.Assert(k.HostKeyCallback(host3Addr+":2223", &net.TCPAddr{Port: 2223}, key), Equals, HostNotFoundError) c.Assert(k.HostKeyCallback(host1Addr+":2222", &net.TCPAddr{Port: 2222}, key), Equals, HostNotFoundError) c.Assert(k.HostKeyCallback(host12Addr+":22", addr, key), IsNil) // hash match // Make sure output is the same as input var output bytes.Buffer c.Assert(k.Marshal(&output), IsNil) c.Assert(output.String(), Equals, input.String()) // Test AppendHost with Writer var output2 bytes.Buffer var input2 bytes.Buffer c.Assert(k.AppendHost("new1.example.com:2223", key, &output2), IsNil) input2.WriteString("[new1.example.com]:2223") input2.WriteString(sep) input2.Write(keyBytes) input2.WriteString("\n") input.Write(input2.Bytes()) c.Assert(output2.String(), Equals, input2.String()) // Test AppendHost without Writer c.Assert(k.AppendHost("new2.example.com:22", key, nil), IsNil) input.WriteString("new2.example.com") input.WriteString(sep) input.Write(keyBytes) input.WriteString("\n") output.Reset() c.Assert(k.Marshal(&output), IsNil) c.Assert(output.String(), Equals, input.String()) }
func NewLibvirtLXCBackend(state *State, portAlloc map[string]*ports.Allocator, volPath, logPath, initPath string) (Backend, error) { libvirtc, err := libvirt.NewVirConnection("lxc:///") if err != nil { return nil, err } pinkertonCtx, err := pinkerton.BuildContext("aufs", "/var/lib/docker") if err != nil { return nil, err } if err := writeResolvConf("/etc/flynn/resolv.conf"); err != nil { return nil, fmt.Errorf("Could not create resolv.conf: %s", err) } b := random.Bytes(5) bridgeMAC := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4]) network, err := libvirtc.LookupNetworkByName(libvirtNetName) if err != nil { n := <.Network{ Name: libvirtNetName, Bridge: lt.Bridge{Name: bridgeName, STP: "off"}, IP: lt.IP{Address: bridgeAddr.String(), Netmask: bridgeMask}, MAC: lt.MAC{Address: bridgeMAC}, } network, err = libvirtc.NetworkDefineXML(string(n.XML())) if err != nil { return nil, err } } active, err := network.IsActive() if err != nil { return nil, err } if !active { if err := network.Create(); err != nil { return nil, err } } // We need to explicitly assign the MAC address to avoid it changing to a lower value // See: https://github.com/flynn/flynn/issues/223 if err := netlink.NetworkSetMacAddress(bridgeName, bridgeMAC); err != nil { return nil, err } iptables.RemoveExistingChain("FLYNN", bridgeName) chain, err := iptables.NewChain("FLYNN", bridgeName) if err != nil { return nil, err } if err := ioutil.WriteFile("/proc/sys/net/ipv4/conf/"+bridgeName+"/route_localnet", []byte("1"), 0666); err != nil { return nil, err } return &LibvirtLXCBackend{ LogPath: logPath, VolPath: volPath, InitPath: initPath, libvirt: libvirtc, state: state, ports: portAlloc, pinkerton: pinkertonCtx, forwarder: ports.NewForwarder(net.ParseIP("0.0.0.0"), chain), logs: make(map[string]*logbuf.Log), containers: make(map[string]*libvirtContainer), }, nil }
func (s *SchedulerSuite) TestTCPApp(t *c.C) { r, err := s.client.GetAppRelease("gitreceive") t.Assert(err, c.IsNil) imageID := r.Processes["app"].Env["SLUGRUNNER_IMAGE_ID"] app := &ct.App{} t.Assert(s.client.CreateApp(app), c.IsNil) artifact := &ct.Artifact{Type: "docker", URI: "https://registry.hub.docker.com/flynn/slugrunner?id=" + imageID} t.Assert(s.client.CreateArtifact(artifact), c.IsNil) release := &ct.Release{ ArtifactID: artifact.ID, Processes: map[string]ct.ProcessType{ "echo": { Ports: []ct.Port{{Proto: "tcp"}}, Cmd: []string{"sdutil exec -s echo-service:$PORT socat -v tcp-l:$PORT,fork exec:/bin/cat"}, Entrypoint: []string{"sh", "-c"}, }, }, } t.Assert(s.client.CreateRelease(release), c.IsNil) t.Assert(s.client.SetAppRelease(app.ID, release.ID), c.IsNil) stream, err := s.client.StreamJobEvents(app.ID) defer stream.Close() if err != nil { t.Error(err) } t.Assert(flynn("/", "-a", app.Name, "scale", "echo=1"), Succeeds) newRoute := flynn("/", "-a", app.Name, "route", "add", "tcp", "-s", "echo-service") t.Assert(newRoute, Succeeds) t.Assert(newRoute.Output, Matches, `.+ on port \d+`) str := strings.Split(strings.TrimSpace(string(newRoute.Output)), " ") port := str[len(str)-1] waitForJobEvents(t, stream.Events, map[string]int{"echo": 1}) // use Attempts to give the processes time to start if err := Attempts.Run(func() error { servAddr := routerIP + ":" + port conn, err := net.Dial("tcp", servAddr) defer conn.Close() if err != nil { return err } echo := random.Bytes(16) _, err = conn.Write(echo) if err != nil { return err } reply := make([]byte, 16) _, err = conn.Read(reply) if err != nil { return err } t.Assert(reply, c.DeepEquals, echo) return nil }); err != nil { t.Error(err) } }