diff --git a/provisioning/resources/control-plane/change_domain_name.go b/provisioning/resources/control-plane/change_domain_name.go new file mode 100644 index 00000000..bd9c1102 --- /dev/null +++ b/provisioning/resources/control-plane/change_domain_name.go @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2016-2017 Snowplow Analytics Ltd. + * All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache + * License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. + * + * See the Apache License Version 2.0 for the specific language + * governing permissions and limitations there under. + */ + +package main + +import ( + "io/ioutil" +) + +func changeDomainName(configPath string, domainName string) error { + lines, err := fileToLines(configPath) + if err != nil { + return err + } + + // write domain name to first line of Caddy config + lines[0] = domainName + " *:80 {" + // placeholder email address, not important + lines[1] = " tls example@example.com" + + fileContent := "" + for _, line := range lines { + fileContent += line + fileContent += "\n" + } + + return ioutil.WriteFile(configPath, []byte(fileContent), 0644) +} diff --git a/provisioning/resources/control-plane/change_domain_name_test.go b/provisioning/resources/control-plane/change_domain_name_test.go new file mode 100644 index 00000000..d3c735a5 --- /dev/null +++ b/provisioning/resources/control-plane/change_domain_name_test.go @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2016-2017 Snowplow Analytics Ltd. + * All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache + * License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. + * + * See the Apache License Version 2.0 for the specific language + * governing permissions and limitations there under. + */ + +package main + +import ( + "github.com/stretchr/testify/assert" + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func TestChangeDomainName(t *testing.T) { + assert := assert.New(t) + + caddyConfigHeadBefore := + `*:80 { + tls off + basicauth username_test password_test { + /home + /kibana + /elasticsearch + /control-plane + /_plugin + } +` + expectedCaddyConfigHeadAfter := + `example.com *:80 { + tls example@example.com + basicauth username_test password_test { + /home + /kibana + /elasticsearch + /control-plane + /_plugin + } +` + dir, err := ioutil.TempDir("", "testDir") + assert.Nil(err) + + defer os.RemoveAll(dir) + + tmpfn := filepath.Join(dir, "tmpfile") + + err = ioutil.WriteFile(tmpfn, []byte(caddyConfigHeadBefore), 0666) + assert.Nil(err) + + err = changeDomainName( + tmpfn, + "example.com", + ) + assert.Nil(err) + + caddyConfigAfter, err := ioutil.ReadFile(tmpfn) + assert.Nil(err) + + assert.True(expectedCaddyConfigHeadAfter == string(caddyConfigAfter)) +} diff --git a/provisioning/resources/control-plane/main.go b/provisioning/resources/control-plane/main.go index 98841d7f..e1a7395a 100644 --- a/provisioning/resources/control-plane/main.go +++ b/provisioning/resources/control-plane/main.go @@ -47,6 +47,7 @@ func main() { http.HandleFunc("/external-iglu", addExternalIgluServer) http.HandleFunc("/local-iglu-apikey", addLocalIgluApikey) http.HandleFunc("/credentials", changeUsernameAndPassword) + http.HandleFunc("/domain-name", addDomainName) log.Fatal(http.ListenAndServe(":10000", nil)) } @@ -256,3 +257,42 @@ func changeUsernameAndPassword(resp http.ResponseWriter, req *http.Request) { http.Error(resp, "", 404) } } + +func addDomainName(resp http.ResponseWriter, req *http.Request) { + if req.Method == "POST" { + req.ParseForm() + + domainNameArr, checkDomainName := req.Form["domain_name"] + if !checkDomainName { + http.Error(resp, "missing parameter", 400) + return + } + domainName := domainNameArr[0] + + err := checkHostDomainName(domainName) + if err != nil { + http.Error(resp, err.Error(), 405) + return + } + + err = changeDomainName( + config.Dirs.Config+"/"+config.ConfigNames.Caddy, + domainName, + ) + if err != nil { + http.Error(resp, err.Error(), 405) + return + } + + err = restartService("caddy") + if err != nil { + http.Error(resp, err.Error(), 500) + return + } + + resp.WriteHeader(http.StatusOK) + io.WriteString(resp, "added successfully") + } else { + http.Error(resp, "", 404) + } +} diff --git a/provisioning/resources/ui/js/components/ControlPlane.tsx b/provisioning/resources/ui/js/components/ControlPlane.tsx index 85a7d031..744cbccb 100644 --- a/provisioning/resources/ui/js/components/ControlPlane.tsx +++ b/provisioning/resources/ui/js/components/ControlPlane.tsx @@ -24,6 +24,7 @@ import UploadEnrichmentsForm from "./ControlPlaneComponents/UploadEnrichments"; import AddExternalIgluServerForm from "./ControlPlaneComponents/AddExternalIgluServer"; import AddLocalIgluApikeyForm from "./ControlPlaneComponents/AddLocalIgluApikey"; import ChangeUsernamePasswordForm from "./ControlPlaneComponents/ChangeUsernamePassword"; +import AddDomainNameForm from "./ControlPlaneComponents/AddDomainName"; export class ControlPlane extends React.Component<{}, {}> { @@ -36,6 +37,7 @@ export class ControlPlane extends React.Component<{}, {}> { + ); } diff --git a/provisioning/resources/ui/js/components/ControlPlaneComponents/AddDomainName.tsx b/provisioning/resources/ui/js/components/ControlPlaneComponents/AddDomainName.tsx new file mode 100644 index 00000000..2cd4696c --- /dev/null +++ b/provisioning/resources/ui/js/components/ControlPlaneComponents/AddDomainName.tsx @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016-2017 Snowplow Analytics Ltd. All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. + */ + +/// +/// +/// +/// + +import React = require('react'); +import ReactDOM = require("react-dom"); +import axios from 'axios'; + +export default React.createClass({ + getInitialState () { + return { + domain_name: '', + disabled: false + }; + }, + + handleChange(evt) { + if (evt.target.name == 'domain_name'){ + this.setState({ + domain_name: evt.target.value + }); + } + }, + + sendFormData() { + var _this = this; + var domainName = this.state.domain_name + + // there is no need to disabled false after + // because connection will be lost after request is sent + // and page will be loaded again + _this.setState({ + disabled: true + }); + var params = new URLSearchParams(); + params.append('domain_name', _this.state.domain_name); + + axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; + axios.post('/control-plane/domain-name', params, {}) + .then(function (response) { + // there is no need to this part because status will be + // 400 in everytime and this will be handled by catch section + }) + .catch(function (error) { + }); + }, + + handleSubmit(event) { + event.preventDefault(); + this.sendFormData(); + }, + + render() { + return ( +
+

Add domain name for TLS:

+
+
+ + +
+
+ +
+
+
+ ); + } +});