mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
09.10.2019 7e95cf92b721376a9a78aa5f498dfe58b8c0e83e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import React from 'react';
import {Alert} from 'reactstrap';
import {
    FormField,
    FormGroup,
    FormLabel,
    FormLabelInputField,
    FormOption,
    FormSelect
} from '../../general/forms/FormComponents';
import PropTypes from "prop-types";
 
class RepoConfigPasswordPanel extends React.Component {
 
    constructor(props) {
        super(props);
        this.state = {
            passwordMethod: 'passwordCommand',
            passwordCreate: null
        };
        this.handlePasswordMethodChange = this.handlePasswordMethodChange.bind(this);
    }
 
    handlePasswordMethodChange = event => {
        event.preventDefault();
        this.setState({[event.target.name]: event.target.value});
        if (event.target.name === 'passwordMethod') {
            const value = event.target.value;
            var passwordCommand = null;
            var passwordCreate = null;
            if (value === 'passwordFile') {
                passwordCommand = 'cat ~/.borg-passphrase';
                passwordCreate = <React.Fragment>
                    Create a file with a password in it in your home directory and use permissions to keep anyone else
                    from
                    reading it:<br/>
                    <div className="command-line">head -c 1024 /dev/urandom | base64 > ~/.borg-passphrase<br/>
                        chmod 400 ~/.borg-passphrase
                    </div>
                </React.Fragment>;
            } else if (value === 'macos-keychain') {
                passwordCommand = 'security find-generic-password -a $USER -s borg-passphrase -w';
                passwordCreate = <React.Fragment>
                    Generate a passphrase and use security to save it to your login (default) keychain:<br/>
                    <div className="command-line">security add-generic-password -D secret -U -a $USER -s borg-passphrase
                        -w $(head -c 1024 /dev/urandom | base64)
                    </div>
                </React.Fragment>;
            } else if (value === 'gnome-keyring') {
                passwordCommand = 'secret-tool lookup borg-repository repo-name';
                passwordCreate = <React.Fragment>
                    First ensure libsecret-tools, gnome-keyring and libpam-gnome-keyring are installed. If
                    libpam-gnome-keyring wasn’t already installed, ensure it runs on login:<br/>
                    <div className="command-line">sudo sh -c "echo session optional pam_gnome_keyring.so auto_start >>
                        /etc/pam.d/login"<br/>
                        sudo sh -c "echo password optional pam_gnome_keyring.so >> /etc/pam.d/passwd"<br/>
                        # you may need to relogin afterwards to activate the login keyring
                    </div>
                    Then add a secret to the login keyring:
                    <div className="command-line">head -c 1024 /dev/urandom | base64 | secret-tool store borg-repository
                        repo-name --label="Borg Passphrase"</div>
                </React.Fragment>;
            } else if (value === 'kwallet') {
                passwordCommand = 'kwalletcli -e borg-passphrase -f Passwords';
                passwordCreate = <React.Fragment>
                    Ensure kwalletcli is installed, generate a passphrase, and store it in your “wallet”:<br/>
                    <div className="command-line">head -c 1024 /dev/urandom | base64 | kwalletcli -Pe borg-passphrase -f
                        Passwords
                    </div>
                </React.Fragment>;
            }
            if (passwordCommand) {
                this.props.setRepoValue('passwordCommand', passwordCommand);
            }
            this.setState({'passwordCreate': passwordCreate});
        }
    }
 
 
    render() {
        var passwordMethods = [['password-command', 'Password command'],
            ['passwordFile', 'Password file'],
            ['macos-keychain', 'Mac OS X keychain'],
            ['gnome-keyring', 'GNOME keyring'],
            ['kwallet', 'KWallet'],
            ['passphrase', 'Passphrase (not recommended)'],
            ['none', 'No password (no encryption, not recommended)']
        ];
        let encrypted = true;
        if (this.props.encryption === 'none' || this.state.passwordMethod === 'none') {
            encrypted = false;
        }
        return <React.Fragment>
            <FormGroup
                className={this.props.encryption === 'none' ? 'hidden' : null}
            >
                <FormLabel length={2}>{'Password method'}</FormLabel>
                <FormField length={4}>
                    <FormSelect
                        value={this.state.passwordMethod}
                        name={'passwordMethod'}
                        onChange={this.handlePasswordMethodChange}
                    >
                        {passwordMethods
                            .map((entry) => <FormOption label={entry[1]} value={entry[0]}
                                                        key={entry[0]}/>)}
                    </FormSelect>
                </FormField>
            </FormGroup>
            <FormGroup className={!this.state.passwordCreate ? 'hidden' : null}>
                <FormLabel length={2}>{'Passphrase creation info'}</FormLabel>
                <FormField length={10}>
                    {this.state.passwordCreate}
                </FormField>
            </FormGroup>
            <FormLabelInputField label={'Password command'} fieldLength={12}
                                 name={'passwordCommand'} value={this.props.repoConfig.passwordCommand}
                                 onChange={this.props.handleRepoConfigChange}
                                 placeholder="Enter the password command to get the command from or choose a method above."
                                 className={!encrypted || this.state.passwordMethod === 'passphrase' ? 'hidden' : null}
            />
            <FormLabelInputField label={'Password'} fieldLength={6} type={'password'}
                                 name={'passphrase'} value={this.props.repoConfig.passphrase}
                                 onChange={this.props.handleRepoConfigChange}
                                 hint={"It's recommended to use password command instead."}
                                 className={(!encrypted || this.state.passwordMethod !== 'passphrase') ? 'hidden' : null}
            />
            <FormGroup className={!encrypted ? 'hidden' : null}>
                <FormField length={2}>
                </FormField>
                <FormField length={10}>
                    <Alert
                        color={'warning'}
                    >
                        Please keep a copy of your password safe! If your password get lost, your backup might be
                        lost!
                    </Alert>
                </FormField>
            </FormGroup>
            <FormGroup className={encrypted ? 'hidden' : null}>
                <FormField length={2}>
                </FormField>
                <FormField length={10}>
                    <Alert
                        color={'danger'}
                    >
                        You backup isn't encrpyted! You should ensure, that your destination storage is encrypted
                        and protected.
                    </Alert>
                </FormField>
            </FormGroup>
        </React.Fragment>;
    }
}
 
RepoConfigPasswordPanel.propTypes = {
    handleRepoConfigChange: PropTypes.func.isRequired,
    setRepoValue: PropTypes.func.isRequired,
    repoConfig: PropTypes.object.isRequired,
    encryption: PropTypes.string
};
 
RepoConfigPasswordPanel.defaultProps = {
    encryption: 'none'
};
 
export default RepoConfigPasswordPanel;