Wie kopiere ich Dateien, die root-Zugriff benötigen, mit scp?


167

Ich habe einen Ubuntu-Server, zu dem ich über SSH eine Verbindung herstelle.

Ich muss Dateien von meinem Computer /var/www/auf den Server hochladen , deren /var/www/Eigentümer die Dateien sind root.

Wenn ich PuTTY benutze, muss ich nach dem Anmelden sudo suzuerst mein Passwort eingeben, um Dateien ändern zu können /var/www/.

Aber wenn ich Dateien mit WinSCP kopiere, kann ich keine Dateien in erstellen / ändern /var/www/, da der Benutzer, mit dem ich mich verbinde, keine Berechtigungen für Dateien in hat /var/www/und ich nicht sagen kann, sudo suwie ich es bei einer SSH-Sitzung tue .

Weißt du, wie ich damit umgehen könnte?

Wenn ich an meinem lokalen Computer arbeiten würde, würde ich anrufen, gksudo nautilusaber in diesem Fall habe ich nur Terminalzugriff auf den Computer.


Dies scheint eher eine Frage für Ihren virtuellen Server-Anbieter oder für die Putty- oder Winscp-Entwickler zu sein.
Dobey

7
@dobey du offensichtlich falsch, es geht um Ubuntu Privilegien!
Dimitris Sapikas

7
Warum ist das geschlossen? Dies ist eine absolut zutreffende Frage zum Kopieren von Dateien mit scp - jeder Webentwickler ist mit dieser Situation vertraut
Sergey


Ich habe ein ähnliches Problem. Ich erstelle eine Datei (in diesem Fall HTML) auf einem Windows-Computer und versuche, sie mit WinSCP in den Ordner / var / www / html / website zu kopieren. Und es heißt, dass es ein Berechtigungsproblem gibt. Da ich in meinen / home-Ordner kopieren kann, habe ich die Datei in zwei Schritten kopiert, aber es ist nicht sehr praktisch :-) Ich habe versucht, meinen Benutzer zur www-Datengruppe hinzuzufügen, aber es hat nicht geholfen. Irgendeine Idee, warum das Hinzufügen zu www-data dem Benutzer immer noch nicht erlaubt, eine Datei in einen Ordner zu kopieren, der der www-data group gehört?
JanezKranjski

Antworten:


125

Du hast recht, es gibt keine sudobei der Arbeit mit scp. Eine Problemumgehung besteht darin scp, Dateien in ein Verzeichnis hochzuladen, in dem Ihr Benutzer Berechtigungen zum Erstellen von Dateien hat, sich dann über ssh anzumelden und sudoDateien an ihren endgültigen Speicherort zu verschieben / kopieren.

scp -r folder/ user@server.tld:/some/folder/you/dont/need/sudo
ssh user@server.tld
 $ sudo mv /some/folder /some/folder/requiring/perms 
# YOU MAY NEED TO CHANGE THE OWNER like:
# sudo chown -R user:user folder

Eine andere Lösung wäre, die Berechtigungen / den Besitz der Verzeichnisse zu ändern, in die Sie die Dateien hochladen, damit Ihr nicht privilegierter Benutzer in diese Verzeichnisse schreiben kann.

Im Allgemeinen sollte das Arbeiten im rootKonto eine Ausnahme sein, keine Regel - die Art und Weise, wie Sie Ihre Frage formulieren, lässt mich denken, dass Sie sie ein wenig missbrauchen, was wiederum zu Problemen mit Berechtigungen führt - unter normalen Umständen, die Sie nicht benötigen Super-Administrator-Rechte, um auf Ihre eigenen Dateien zuzugreifen.

Technisch gesehen können Sie Ubuntu so konfigurieren, dass eine direkte Remote-Anmeldung als rootzulässig ist. Diese Funktion ist jedoch aus einem bestimmten Grund deaktiviert. Ich rate Ihnen daher dringend davon ab.


Ich habe nicht die erste Lösung gefunden. Könnten Sie bitte etwas spezieller sein?
Dimitris Sapikas

Wenn ich meine eigenen Dateien sage, meine ich / var / www, ich benutze mein vps als Webserver .... auf meinem eigenen Ordner habe ich vollen Zugriff
Dimitris Sapikas

7
Re. die erste lösung. 1. scp -R mysite dimitris@myserver.com:/home/dimitris/2. ssh dimitris@myserver.com3. sudo mv ~/mysite /var/www- es ist ein 2-Schritt-Prozess, zuerst Sie scpdie Dateien zu Ihrem Heimatverzeichnis, dann melden Sie sich über ssh und kopieren / verschieben Sie die Dateien, wo sie sein sollten
Sergey

36

Eine andere Methode ist das Kopieren mit tar + ssh anstelle von scp:

tar -c -C ./my/local/dir \
  | ssh dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"

2
Dies ist der beste Weg, dies zu tun.
mttdbrd

2
Ich kann diese Methode nicht erfolgreich zum Laufen bringen. Wie geschrieben bekomme ich sudo: sorry, you must have a tty to run sudo. Wenn ich "-t" hinzufüge, um ein TTY zuzuweisen, erhalte ich Pseudo-terminal will not be allocated because stdin is not a terminal.. Ohne passwortloses sudo kann ich das nicht sehen.
IBBoard

1
@IBBoard: versuchen Sie die Lösung hier mit ssh-t:ssh -t dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
Alexander Bird

2
@AlexanderBird Obwohl das in vielen Fällen funktioniert, bin ich mir nicht sicher, ob es hier funktioniert, da wir versuchen, einen Tarball über die SSH-Verbindung zu leiten. Siehe serverfault.com/questions/14389/…
IBBoard,

Dies ist, was schließlich für mich gearbeitet hat. Sie haben keine Berechtigungen für eine Remote-Datei, die Sie auf lokal kopieren möchten. Führen Sie eine aus sudo tar, archivieren Sie sie, ändern Sie die Berechtigungen mit chmodund chownund kopieren Sie sie dann auf lokal. Besonders wenn es ein Verzeichnis ist.
Forumulator

27

Schneller Weg

Vom Server zum lokalen Computer:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file

Vom lokalen Computer zum Server:

cat /home/user/file | ssh user@server "sudo tee -a /etc/dir/file"

5
Diese Antwort wird unterschätzt. Es ist einfach, sauber, liest oder schreibt eine Root-Datei mit einer einzigen atomaren Operation und erfordert nichts, was nicht garantiert vorhanden ist, wenn Sie scp verwenden. Hauptnachteil ist, dass Berechtigungen nicht kopiert werden. Wenn Sie das wollen, ist die Teerlösung besser. Dies ist eine mächtige Technik, besonders wenn sie mit Xargs / Bash-Magie kombiniert wird, um Pfade zu durchqueren.
markgo2k

Ich denke, die Frage war über das Hochladen einer Datei von lokal auf remote und nicht umgekehrt
Korayem

1
Schön gemacht. Das ist genau das, wonach ich sowohl nach oben als auch nach unten gesucht habe. Vielen Dank
Jeremy

Verdient es mit Sicherheit, die beste Antwort zu sein.
Andrew Watson

Kann dies auch für ein Verzeichnis anstelle einer Datei durchgeführt werden?
Lucidbrot

26

Sie können auch verwenden ansible, um dies zu erreichen.

Kopieren Sie mit dem ansible- copyModul auf den Remote-Host :

ansible -i HOST, -b -m copy -a "src=SRC_FILEPATH dest=DEST_FILEPATH" all

Abrufen vom Remote-Host mithilfe des ansible- fetchModuls :

ansible -i HOST, -b -m fetch -a "src=SRC_FILEPATH dest=DEST_FILEPATH flat=yes" all

HINWEIS:

  • Das Komma in der -i HOST,Syntax ist kein Tippfehler. Dies ist die Möglichkeit, ansible zu verwenden, ohne eine Inventardatei zu benötigen.
  • -bbewirkt, dass die Aktionen auf dem Server als root ausgeführt werden. -berweitert sich zu --becomeund der Standard --become-userist root, wobei der Standard --become-methodsudo ist.
  • flat=yeskopiert nur die Datei, kopiert nicht den gesamten Remote-Pfad, der zur Datei führt
  • Die Verwendung von Platzhaltern in den Dateipfaden wird von diesen ansiblen Modulen nicht unterstützt.
  • Das Kopieren eines Verzeichnisses wird vom copyModul unterstützt, nicht jedoch vom fetchModul.

Spezifische Aufforderung für diese Frage

Hier ist ein Beispiel, das spezifisch und vollständig spezifiziert ist, vorausgesetzt, das Verzeichnis auf Ihrem lokalen Host, das die zu verteilenden Dateien enthält, ist sourcedirund der Hostname des Remote-Ziels lautet hostname:

cd sourcedir && \
ansible \
   --inventory-file hostname, \ 
   --become \
   --become-method sudo \
   --become-user root \
   --module-name copy \
   --args "src=. dest=/var/www/" \
   all

Mit dem prägnanten Aufruf:

cd sourcedir && \
ansible -i hostname, -b -m copy -a "src=. dest=/var/www/" all

PS, mir ist klar, dass das Sprichwort "nur dieses fantastische Werkzeug installieren" eine Art tonlose Antwort ist. Aber ich habe ansible gefunden sein Super nützlich für die Verwaltung von Remote - Servern, so dass es die Installation werden Sie sicherlich andere Vorteile mit sich bringen Dateien über den Einsatz.


Diese Antwort gefällt mir, aber ich empfehle Ihnen, sie auf die gestellte Frage zu richten, im Gegensatz zu allgemeineren Kommentaren, bevor Sie eine positive Bewertung abgeben. so etwas wieansible -i "hostname," all -u user --become -m copy -a ...
Mike D

@ MikeD: Wie sehen die obigen Änderungen aus?
erik.weathers

1
Möchten Sie -i 'host,'eine gültige Syntax haben? Ich denke, es ist leicht, solche Satzzeichen zu verlieren, wenn man einen Befehl liest. (Für den Leser meine ich, wenn nicht die Shell.)
Mwfearnley

1
@mwfearnley: sicher, die Shell behandelt -i 'host,'und wie -i host,oder -i "host,". Im Allgemeinen ziehe ich es vor, diese Aufrufe so kurz wie möglich zu halten, um sie nicht zu entmutigen, aber Sie sollten sich frei fühlen, sie so ausführlich und explizit zu gestalten, wie Sie es für die Klarheit für erforderlich halten.
erik.weathers

2
Ein guter Weg, um über den Tellerrand hinaus zu denken! Große Verwendung von Ansible
jonatan

12

Wenn Sie das Programm ausführen sudo su, werden alle von Ihnen erstellten Dateien Eigentum von root, es ist jedoch standardmäßig nicht möglich, sich mit ssh oder scp direkt als root anzumelden. Es ist auch nicht möglich, sudo mit scp zu verwenden, daher können die Dateien nicht verwendet werden. Beheben Sie dieses Problem, indem Sie das Eigentum an Ihren Dateien geltend machen:

Angenommen, Ihr Benutzername lautet dimitri, können Sie diesen Befehl verwenden.

sudo chown -R dimitri:dimitri /home/dimitri

Wie in anderen Antworten bereits erwähnt, werden von nun an "Ubuntu" -Logins mit sudo und nicht mehr mit root verwendet. Es ist ein nützliches Paradigma mit großen Sicherheitsvorteilen.


Ich benutze diese Lösung auf jeden Fall, aber wenn ich vollen Zugriff auf mein eigenes Dateisystem bekommen könnte, möchte ich nicht sudo chow ...für jedes einzelne Verzeichnis
Folgendes eingeben

2
Es wird dringend davon abgeraten, den Besitz aller Systemdateien an den Benutzer zu ändern, um die Weitergabe zu vereinfachen. Hierdurch kann jeder Benutzerraumfehler, der auftaucht, die Sicherheit Ihres Systems erheblich beeinträchtigen. Es ist viel besser, den Besitz der Dateien zu ändern, die Sie von SCP ändern oder aktualisieren müssen, aber alles andere dem root zu überlassen (wie es sein soll). Das heißt, das -Rin chownweist es an, den Besitz dieses Verzeichnisses und aller untergeordneten Dateien und Verzeichnisse rekursiv zu ändern ... damit Sie alles tun können, was Sie wollen.
Trognanders

hmm .... das scheint gut zu funktionieren, danke! Entschuldigung, ich kann nicht upvote (System erlaubt mir nicht zu tun ...)
Dimitris Sapikas

11

Möglicherweise ist die Verwendung von rsync( Cygwin / cwRsync in Windows) über SSH der beste Weg ?

So laden Sie beispielsweise Dateien mit dem Eigentümer hoch www-data:

rsync -a --rsync-path="sudo -u www-data rsync" path_to_local_data/ login@srv01.example.com:/var/www

Wenn Sie in Ihrem Fall Root-Rechte benötigen, sieht der Befehl folgendermaßen aus:

rsync -a --rsync-path="sudo rsync" path_to_local_data/ login@srv01.example.com:/var/www

Siehe: scp zum Remote-Server mit sudo .


5

Wenn Sie die OpenSSH-Tools anstelle von PuTTY verwenden, können Sie dies erreichen, indem Sie die scpDateiübertragung auf dem Server mit initiieren sudo. Stellen Sie sicher, dass sshdauf Ihrem lokalen Computer ein Daemon ausgeführt wird. Mit können ssh -RSie dem Server eine Möglichkeit geben, mit Ihrem Computer in Kontakt zu treten.

Auf Ihrem Computer:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Dadurch werden Sie nicht nur beim Server angemeldet, sondern jede Verbindung, die über den Port 11111 des Servers hergestellt wird, an den Port 22 Ihres Computers weitergeleitet: den Port, den Sie abhören sshd.

Starten Sie auf dem Server die Dateiübertragung folgendermaßen:

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .

1

Sie können ein Skript verwenden, das ich geschrieben habe und von diesem Thema inspiriert wurde:

touch /tmp/justtest && scpassudo /tmp/justtest remoteuser@ssh.superserver.com:/tmp/

das erfordert aber ein paar verrückte sachen (was übrigens automatisch per script erledigt wird)

  1. Der Server, an den die Datei gesendet wird, fragt beim Herstellen der SSH-Verbindung zum Quellcomputer nicht mehr nach dem Kennwort
  2. Aufgrund fehlender sudo-Eingabeaufforderung auf dem Server wird sudo nicht mehr nach dem Kennwort für den Benutzer auf dem Remotecomputer fragen

Hier geht das Skript:

interface=wlan0
if [[ $# -ge 3 ]]; then interface=$3; fi
thisIP=$(ifconfig | grep $interface -b1 | tail -n1 | egrep -o '[0-9.]{4,}' -m1 | head -n 1)
thisUser=$(whoami)
localFilePath=/tmp/justfortest
destIP=192.168.0.2
destUser=silesia
#dest 
#destFolderOnRemoteMachine=/opt/glassfish/glassfish/
#destFolderOnRemoteMachine=/tmp/

if [[ $# -eq 0 ]]; then 
echo -e "Send file to remote server to locatoin where root permision is needed.\n\tusage: $0 local_filename [username@](ip|host):(remote_folder/|remote_filename) [optionalInterface=wlan0]"
echo -e "Example: \n\ttouch /tmp/justtest &&\n\t $0 /tmp/justtest remoteuser@ssh.superserver.com:/tmp/ "
exit 1
fi

localFilePath=$1

test -e $localFilePath 

destString=$2
usernameAndHost=$(echo $destString | cut -f1 -d':')

if [[ "$usernameAndHost" == *"@"* ]]; then
destUser=$(echo $usernameAndHost | cut -f1 -d'@')
destIP=$(echo $usernameAndHost | cut -f2 -d'@')
else
destIP=$usernameAndHost
destUser=$thisUser
fi

destFolderOnRemoteMachine=$(echo $destString | cut -f2 -d':')

set -e #stop script if there is even single error

echo 'First step: we need to be able to execute scp without any user interaction'
echo 'generating public key on machine, which will receive file'
ssh $destUser@$destIP 'test -e ~/.ssh/id_rsa.pub -a -e ~/.ssh/id_rsa || ssh-keygen -t rsa'
echo 'Done'

echo 'Second step: download public key from remote machine to this machine so this machine allows remote machine (this one receiveing file) to login without asking for password'

key=$(ssh $destUser@$destIP 'cat ~/.ssh/id_rsa.pub')
if ! grep "$key" ~/.ssh/authorized_keys; then
echo $key >> ~/.ssh/authorized_keys
echo 'Added key to authorized hosts'
else
echo "Key already exists in authorized keys"
fi

echo "We will want to execute sudo command remotely, which means turning off asking for password"
echo 'This can be done by this tutorial http://stackoverflow.com/a/10310407/781312'
echo 'This you have to do manually: '
echo -e "execute in new terminal: \n\tssh $destUser:$destIP\nPress enter when ready"
read 
echo 'run there sudo visudo'
read
echo 'change '
echo '    %sudo   ALL=(ALL:ALL) ALL'
echo 'to'
echo '    %sudo   ALL=(ALL:ALL) NOPASSWD: ALL'
echo "After this step you will be done."
read

listOfFiles=$(ssh $destUser@$destIP "sudo ls -a")

if [[ "$listOfFiles" != "" ]]; then 
echo "Sending by executing command, in fact, receiving, file on remote machine"
echo 'Note that this command (due to " instead of '', see man bash | less -p''quotes'') is filled with values from local machine'
echo -e "Executing \n\t""identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"" \non remote machine"
ssh $destUser@$destIP "identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"
ssh $destUser@$destIP "ls ${destFolderOnRemoteMachine%\\\\n}/$(basename $localFilePath)"
if [[ ! "$?" -eq 0 ]]; then echo "errror in validating"; else echo -e "SUCCESS! Successfully sent\n\t$localFilePath \nto \n\t$destString\nFind more at http://arzoxadi.tk"; fi
else
echo "something went wrong with executing sudo on remote host, failure"

fi
ENDOFSCRIPT
) | sudo tee /usr/bin/scpassudo && chmod +x /usr/bin/scpassudo

@Braiam yeah, klar, sorry für den Link, das Skript ist ziemlich lang und das war der Grund :)
test30

1

Sie können ssh, sudo und zB tar kombinieren, um Dateien zwischen Servern zu übertragen, ohne sich als root anmelden zu können und ohne die Berechtigung, mit Ihrem Benutzer auf die Dateien zuzugreifen. Das ist etwas umständlich, deshalb habe ich ein Skript geschrieben, um dies zu unterstützen. Sie finden das Skript hier: https://github.com/sigmunau/sudoscp

oder hier:

#! / bin / bash
res = 0
von = $ 1
bis = 2 $
Verschiebung
Verschiebung
files = "$ @"
if test -z "$ from" -o -z "$ to" -o -z "$ files"
dann
    echo "Verwendung: $ 0 (Datei) *"
    echo "Beispiel: $ 0 server1 server2 / usr / bin / myapp"
    Ausfahrt 1
fi

read -s -p "Passwort eingeben:" sudopassword
Echo ""
temp1 = $ (mktemp)
temp2 = $ (mktemp)
(Echo "$ sudopassword"; Echo "$ sudopassword" | ssh $ von sudo-S tar c-P-C / $ files 2> $ temp1) | ssh $ zu sudo-S tar x-v-P-C / 2 > $ temp2
Quellen = $ {PIPESTATUS [0]}
wenn [$? -ne 0 -o $ sourceres -ne 0]
dann
    Echo "Fehler!" > & 2
    echo "$ from output:"> & 2
    cat $ temp1> & 2
    Echo ""> & 2
    Echo "$ zur Ausgabe:"> & 2
    cat $ temp2> & 2
    res = 1
fi

rm $ temp1 $ temp2
Beenden Sie $ res

Willkommen bei Ask Ubuntu. Könnten Sie bitte das Skript in Ihre Antwort aufnehmen? Ich weiß, dass es unwahrscheinlich ist, aber wenn das Github-Repo jemals entfernt oder die URL geändert würde, wäre die Antwort ungültig. Es ist besser, das Skript direkt einzuschließen und das Github-Repo als Quelle zu belassen.
Michael Lindman

0

Hier ist eine modifizierte Version von Willie Wheelers Antwort, die die Datei (en) über tar überträgt, aber auch die Übergabe eines Passworts an sudo auf dem Remote-Host unterstützt.

(stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) \
  | ssh remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""

Das gewisse Extra an Magie ist hier die Option -S für sudo. Aus der sudo-Manpage:

-S, --stdin Schreiben Sie die Eingabeaufforderung zum Standardfehler und lesen Sie das Kennwort von der Standardeingabe, anstatt das Endgerät zu verwenden. Dem Passwort muss ein Zeilenumbruch folgen.

Jetzt wollen wir eigentlich, dass die Ausgabe von tar in ssh umgeleitet wird. Dadurch wird die Standardeingabe von ssh in die Standardeingabe von tar umgeleitet, sodass keine Möglichkeit mehr besteht, das Kennwort vom interaktiven Terminal an sudo zu übergeben. (Wir könnten die ASKPASS-Funktion von sudo auf der Remote-Seite verwenden, aber das ist eine andere Geschichte.) Wir können das Passwort in sudo einbinden, indem wir es im Voraus erfassen und der tar-Ausgabe voranstellen, indem wir diese Operationen in einer Subshell ausführen und die Ausgabe von weiterleiten die Unterschale in ssh. Dies hat auch den zusätzlichen Vorteil, dass eine Umgebungsvariable, die unser Passwort enthält, nicht in unserer interaktiven Shell baumelt.

Sie werden feststellen, dass ich "read" nicht mit der Option -p ausgeführt habe, um eine Eingabeaufforderung zu drucken. Dies liegt daran, dass die Passwortabfrage von sudo bequem über ssh an den stderr unserer interaktiven Shell zurückgegeben wird. Sie fragen sich vielleicht, wie sudo ausgeführt wird, wenn es in ssh rechts von unserer Pipe ausgeführt wird. Wenn wir mehrere Befehle ausführen und die Ausgabe von einem in einen anderen umleiten, führt die übergeordnete Shell (in diesem Fall die interaktive Shell) jeden Befehl in der Reihenfolge unmittelbar nach der Ausführung des vorherigen aus. Wenn jeder Befehl hinter einer Pipe ausgeführt wird, fügt die übergeordnete Shell die Standardausgabe der linken Seite der Standardausgabe der rechten Seite hinzu (leitet sie um). Die Ausgabe wird dann zur Eingabe, wenn sie Prozesse durchläuft.

$ (stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) | ssh 
remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
[sudo] password for bruce: 
[1]+  Stopped                 ( stty -echo; read passwd; stty echo; echo 
$passwd; tar -cz foo.* ) | ssh remote_host "sudo -S bash -c \"tar -C 
/var/www/ -xz; echo\""

$ pstree -lap $$
bash,7168
  ├─bash,7969
  ├─pstree,7972 -lap 7168
  └─ssh,7970 remote_host sudo -S bash -c "tar -C /var/www/ -xz; echo"`

Unsere interaktive Shell ist PID 7168, unsere Subshell ist PID 7969 und unser SSH-Prozess ist PID 7970.

Der einzige Nachteil ist, dass beim Lesen Eingaben akzeptiert werden, bevor sudo Zeit hat, die Eingabeaufforderung zurückzusenden. Bei einer schnellen Verbindung und einem schnellen Remote-Host werden Sie dies nicht bemerken, aber möglicherweise, wenn eine der beiden langsam ist. Verzögerungen beeinträchtigen nicht die Möglichkeit, die Eingabeaufforderung einzugeben. Möglicherweise wird es erst angezeigt, nachdem Sie mit der Eingabe begonnen haben.

Hinweis Ich habe meinem lokalen Rechner für die Demo einfach einen Host-Dateieintrag für "remote_Host" hinzugefügt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.